reGenerate Thumbnails Advanced - Version 2.2.0

Version Description

Release date: 9th March 2020 * Reworked and improved the process interface * Option in media library to regenerate just one image * Will check for post_mime_type in posts and fix it when it's empty. * Cookie-based processing removed, now keeps progress as a server setting * Internal processes optimized. * Fixed - WordPress 5.3 image handling and scaled images * Fixed - Metadata not being removed in some cases when "Delete Leftover Image Metadata" is checked. * Fixed - Logger doesn't call wp_upload_dir when not debugging

Download this release

Release Info

Developer petredobrescu
Plugin Icon 128x128 reGenerate Thumbnails Advanced
Version 2.2.0
Comparing to
See all releases

Code changes from version 2.1.0 to 2.2.0

build/shortpixel/PackageLoader.php ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace ReThumbAdvanced\Build;
3
+
4
+ class PackageLoader
5
+ {
6
+ public $dir;
7
+
8
+ public function getComposerFile()
9
+ {
10
+ return json_decode(file_get_contents($this->dir."/composer.json"), 1);
11
+ }
12
+
13
+ public function load($dir)
14
+ {
15
+ $this->dir = $dir;
16
+ $composer = $this->getComposerFile();
17
+
18
+
19
+ if(isset($composer["autoload"]["psr-4"])){
20
+ $this->loadPSR4($composer['autoload']['psr-4']);
21
+ }
22
+ if(isset($composer["autoload"]["psr-0"])){
23
+ $this->loadPSR0($composer['autoload']['psr-0']);
24
+ }
25
+ if(isset($composer["autoload"]["files"])){
26
+ $this->loadFiles($composer["autoload"]["files"]);
27
+ }
28
+ }
29
+
30
+ public function loadFiles($files){
31
+ foreach($files as $file){
32
+ $fullpath = $this->dir."/".$file;
33
+ if(file_exists($fullpath)){
34
+ include_once($fullpath);
35
+ }
36
+ }
37
+ }
38
+
39
+ public function loadPSR4($namespaces)
40
+ {
41
+ $this->loadPSR($namespaces, true);
42
+ }
43
+
44
+ public function loadPSR0($namespaces)
45
+ {
46
+ $this->loadPSR($namespaces, false);
47
+ }
48
+
49
+ public function loadPSR($namespaces, $psr4)
50
+ {
51
+ $dir = $this->dir;
52
+ // Foreach namespace specified in the composer, load the given classes
53
+ foreach ($namespaces as $namespace => $classpaths) {
54
+ if (!is_array($classpaths)) {
55
+ $classpaths = array($classpaths);
56
+ }
57
+ spl_autoload_register(function ($classname) use ($namespace, $classpaths, $dir, $psr4) {
58
+ // Check if the namespace matches the class we are looking for
59
+ if (preg_match("#^".preg_quote($namespace)."#", $classname)) {
60
+ // Remove the namespace from the file path since it's psr4
61
+ if ($psr4) {
62
+ $classname = str_replace($namespace, "", $classname);
63
+ }
64
+
65
+ // $filename = preg_replace("#\\\\#", "", $classname).".php";
66
+ // This is fix for nested classes which were losing a /
67
+ $filename = ltrim($classname .'.php', '\\');
68
+ $filename = str_replace('\\','/', $filename);
69
+
70
+ foreach ($classpaths as $classpath) {
71
+ $fullpath = trailingslashit($dir) . trailingslashit($classpath) .$filename;
72
+ if (file_exists($fullpath)) {
73
+ include_once $fullpath;
74
+ }
75
+ }
76
+ }
77
+ });
78
+ }
79
+ }
80
+ }
build/shortpixel/autoload.php ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ <?php
2
+ require_once (dirname(__FILE__) . "/PackageLoader.php");
3
+ $loader = new ReThumbAdvanced\Build\PackageLoader();
4
+ $loader->load(__DIR__);
5
+
build/shortpixel/composer.json ADDED
@@ -0,0 +1 @@
 
1
+ {"name":"ReThumbAdvanced\/shortpixelmodules","description":"ShortPixel submodules","type":"function","autoload":{"psr-4":{"ReThumbAdvanced\\ShortPixelLogger":"log\/src","ReThumbAdvanced\\Notices":"notices\/src"}}}
build/shortpixel/log/composer.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "shortpixel/log",
3
+ "description": "ShortPixel Logging",
4
+ "version": "1.1.3",
5
+ "type": "library",
6
+ "license": "MIT",
7
+ "authors": [
8
+ {
9
+ "name": "Bas",
10
+ "email": "bas@weblogmechanic.com"
11
+ }
12
+ ],
13
+ "minimum-stability": "dev",
14
+ "require": {},
15
+ "autoload": {
16
+ "psr-4": { "ShortPixel\\ShortPixelLogger\\" : "src" }
17
+ }
18
+ }
build/shortpixel/log/src/DebugItem.php ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // The data models.
3
+ namespace ReThumbAdvanced\ShortPixelLogger;
4
+
5
+
6
+ class DebugItem
7
+ {
8
+ protected $time;
9
+ protected $level;
10
+ protected $message;
11
+ protected $data = array();
12
+ protected $caller = false; // array when filled
13
+
14
+ protected $model;
15
+
16
+ const LEVEL_ERROR = 1;
17
+ const LEVEL_WARN = 2;
18
+ const LEVEL_INFO = 3;
19
+ const LEVEL_DEBUG = 4;
20
+
21
+ public function __construct($message, $args)
22
+ {
23
+ $this->level = $args['level'];
24
+ $data = $args['data'];
25
+
26
+ $this->message = $message;
27
+ $this->time = microtime(true);
28
+
29
+ $this->setCaller();
30
+
31
+ // Add message to data if it seems to be some debug variable.
32
+ if (is_object($this->message) || is_array($this->message))
33
+ {
34
+ $data[] = $this->message;
35
+ $this->message = __('[Data]');
36
+ }
37
+ if (is_array($data) && count($data) > 0)
38
+ {
39
+ $dataType = $this->getDataType($data);
40
+ if ($dataType == 1) // singular
41
+ {
42
+ $this->data[] = print_r($data, true);
43
+ }
44
+ if ($dataType == 2) //array
45
+ {
46
+ foreach($data as $index => $item)
47
+ {
48
+ if (is_object($item) || is_array($item))
49
+ {
50
+ $this->data[] = print_r($item, true);
51
+ }
52
+ }
53
+ }
54
+ } // if
55
+ elseif (! is_array($data)) // this leaves out empty default arrays
56
+ {
57
+ $this->data[] = print_r($data, true);
58
+ }
59
+ }
60
+
61
+ public function getData()
62
+ {
63
+ return array('time' => $this->time, 'level' => $this->level, 'message' => $this->message, 'data' => $this->data, 'caller' => $this->caller);
64
+ }
65
+
66
+ /** Test Data Array for possible values
67
+ *
68
+ * Data can be a collection of several debug vars, a single var, or just an normal array. Test if array has single types,
69
+ * which is a sign the array is not a collection.
70
+ */
71
+ protected function getDataType($data)
72
+ {
73
+ $single_type = array('integer', 'boolean', 'string');
74
+ if (in_array(gettype(reset($data)), $single_type))
75
+ {
76
+ return 1;
77
+ }
78
+ else
79
+ {
80
+ return 2;
81
+ }
82
+ }
83
+
84
+ public function getForFormat()
85
+ {
86
+ $data = $this->getData();
87
+ switch($this->level)
88
+ {
89
+ case self::LEVEL_ERROR:
90
+ $level = 'ERR';
91
+ $color = "\033[31m";
92
+ break;
93
+ case self::LEVEL_WARN:
94
+ $level = 'WRN';
95
+ $color = "\033[33m";
96
+ break;
97
+ case self::LEVEL_INFO:
98
+ $level = 'INF';
99
+ $color = "\033[37m";
100
+ break;
101
+ case self::LEVEL_DEBUG:
102
+ $level = 'DBG';
103
+ $color = "\033[37m";
104
+ break;
105
+
106
+ }
107
+ $color_end = "\033[0m";
108
+
109
+ $data['color'] = $color;
110
+ $data['color_end'] = $color_end;
111
+ $data['level'] = $level;
112
+
113
+ return $data;
114
+
115
+ //return array('time' => $this->time, 'level' => $level, 'message' => $this->message, 'data' => $this->data, 'color' => $color, 'color_end' => $color_end, 'caller' => $this->caller);
116
+
117
+ }
118
+
119
+ protected function setCaller()
120
+ {
121
+ if(PHP_VERSION_ID < 50400) {
122
+ $debug=debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
123
+ } else {
124
+ $debug=debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS,5);
125
+ }
126
+
127
+ $i = 4;
128
+ if (isset($debug[$i]))
129
+ {
130
+ $info = $debug[$i];
131
+ $line = isset($info['line']) ? $info['line'] : 'Line unknown';
132
+ $file = isset($info['file']) ? basename($info['file']) : 'File not set';
133
+
134
+ $this->caller = array('line' => $line, 'file' => $file, 'function' => $info['function']);
135
+ }
136
+
137
+
138
+ }
139
+
140
+
141
+ }
build/shortpixel/log/src/ShortPixelLogger.php ADDED
@@ -0,0 +1,330 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace ReThumbAdvanced\ShortPixelLogger;
3
+
4
+ /*** Logger class
5
+ *
6
+ * Class uses the debug data model for keeping log entries.
7
+ * Logger should not be called before init hook!
8
+ */
9
+ class ShortPixelLogger
10
+ {
11
+ static protected $instance = null;
12
+ protected $start_time;
13
+
14
+ protected $is_active = false;
15
+ protected $is_manual_request = false;
16
+ protected $show_debug_view = false;
17
+
18
+ protected $items = array();
19
+ protected $logPath = false;
20
+ protected $logMode = FILE_APPEND;
21
+
22
+ protected $logLevel;
23
+ protected $format = "[ %%time%% ] %%color%% %%level%% %%color_end%% \t %%message%% \t %%caller%% ( %%time_passed%% )";
24
+ protected $format_data = "\t %%data%% ";
25
+
26
+ protected $hooks = array();
27
+ /* protected $hooks = array(
28
+ 'shortpixel_image_exists' => array('numargs' => 3),
29
+ 'shortpixel_webp_image_base' => array('numargs' => 2),
30
+ 'shortpixel_image_urls' => array('numargs' => 2),
31
+ ); // @todo monitor hooks, but this should be more dynamic. Do when moving to module via config.
32
+ */
33
+
34
+ // utility
35
+ private $namespace;
36
+ private $view;
37
+
38
+ protected $template = 'view-debug-box';
39
+
40
+ /** Debugger constructor
41
+ * Two ways to activate the debugger. 1) Define SHORTPIXEL_DEBUG in wp-config.php. Either must be true or a number corresponding to required LogLevel
42
+ * 2) Put SHORTPIXEL_DEBUG in the request. Either true or number.
43
+ */
44
+ public function __construct()
45
+ {
46
+ $this->start_time = microtime(true);
47
+ $this->logLevel = DebugItem::LEVEL_WARN;
48
+
49
+ $ns = __NAMESPACE__;
50
+ $this->namespace = substr($ns, 0, strpos($ns, '\\')); // try to get first part of namespace
51
+
52
+ if (isset($_REQUEST['SHORTPIXEL_DEBUG'])) // manual takes precedence over constants
53
+ {
54
+ $this->is_manual_request = true;
55
+ $this->is_active = true;
56
+
57
+ if ($_REQUEST['SHORTPIXEL_DEBUG'] === 'true')
58
+ {
59
+ $this->logLevel = DebugItem::LEVEL_INFO;
60
+ }
61
+ else {
62
+ $this->logLevel = intval($_REQUEST['SHORTPIXEL_DEBUG']);
63
+ }
64
+
65
+ }
66
+ else if ( (defined('SHORTPIXEL_DEBUG') && SHORTPIXEL_DEBUG > 0) )
67
+ {
68
+ $this->is_active = true;
69
+ if (SHORTPIXEL_DEBUG === true)
70
+ $this->logLevel = DebugItem::LEVEL_INFO;
71
+ else {
72
+ $this->logLevel = intval(SHORTPIXEL_DEBUG);
73
+ }
74
+ }
75
+
76
+ if (defined('SHORTPIXEL_DEBUG_TARGET') && SHORTPIXEL_DEBUG_TARGET || $this->is_manual_request)
77
+ {
78
+ //$this->logPath = SHORTPIXEL_BACKUP_FOLDER . "/shortpixel_log";
79
+ //$this->logMode = defined('SHORTPIXEL_LOG_OVERWRITE') ? 0 : FILE_APPEND;
80
+ if (defined('SHORTPIXEL_LOG_OVERWRITE')) // if overwrite, do this on init once.
81
+ file_put_contents($this->logPath,'-- Log Reset -- ' .PHP_EOL);
82
+
83
+ }
84
+
85
+ if ($this->is_active)
86
+ {
87
+ /* On Early init, this function might not exist, then queue it when needed */
88
+ if (! function_exists('wp_get_current_user'))
89
+ add_action('init', array($this, 'initView'));
90
+ else
91
+ $this->initView();
92
+ }
93
+
94
+ if ($this->is_active && count($this->hooks) > 0)
95
+ $this->monitorHooks();
96
+ }
97
+
98
+ /** Init the view when needed. Private function ( public because of WP_HOOK )
99
+ * Never call directly */
100
+ public function initView()
101
+ {
102
+ $user_is_administrator = (current_user_can('manage_options')) ? true : false;
103
+
104
+ if ($this->is_active && $this->is_manual_request && $user_is_administrator )
105
+ {
106
+ $content_url = content_url();
107
+ $logPath = $this->logPath;
108
+ $pathpos = strpos($logPath, 'wp-content') + strlen('wp-content');
109
+ $logPart = substr($logPath, $pathpos);
110
+ $logLink = $content_url . $logPart;
111
+
112
+ $this->view = new \stdClass;
113
+ $this->view->logLink = $logLink;
114
+ add_action('admin_footer', array($this, 'loadView'));
115
+ }
116
+ }
117
+
118
+ public static function getInstance()
119
+ {
120
+ if ( self::$instance === null)
121
+ {
122
+ self::$instance = new ShortPixelLogger();
123
+ }
124
+ return self::$instance;
125
+ }
126
+
127
+ public function setLogPath($logPath)
128
+ {
129
+ $this->logPath = $logPath;
130
+ }
131
+ protected function addLog($message, $level, $data = array())
132
+ {
133
+ // $log = self::getInstance();
134
+
135
+ // don't log anything too low or when not active.
136
+ if ($this->logLevel < $level || ! $this->is_active)
137
+ {
138
+ return;
139
+ }
140
+
141
+ // Check where to log to.
142
+ if ($this->logPath === false)
143
+ {
144
+ $upload_dir = wp_upload_dir(null,false,false);
145
+ $this->logPath = $this->setLogPath($upload_dir['basedir'] . '/' . $this->namespace . ".log");
146
+ }
147
+
148
+ $arg = array();
149
+ $args['level'] = $level;
150
+ $args['data'] = $data;
151
+
152
+ $newItem = new DebugItem($message, $args);
153
+ $this->items[] = $newItem;
154
+
155
+ if ($this->is_active)
156
+ {
157
+ $this->write($newItem);
158
+ }
159
+ }
160
+
161
+ /** Writes to log File. */
162
+ protected function write($debugItem, $mode = 'file')
163
+ {
164
+ $items = $debugItem->getForFormat();
165
+ $items['time_passed'] = round ( ($items['time'] - $this->start_time), 5);
166
+ $items['time'] = date('Y-m-d H:i:s', $items['time'] );
167
+
168
+ if ( ($items['caller']) && is_array($items['caller']) && count($items['caller']) > 0)
169
+ {
170
+ $caller = $items['caller'];
171
+ $items['caller'] = $caller['file'] . ' in ' . $caller['function'] . '(' . $caller['line'] . ')';
172
+ }
173
+
174
+ $line = $this->formatLine($items);
175
+
176
+ // try to write to file. Don't write if directory doesn't exists (leads to notices)
177
+ if ($this->logPath && is_dir(dirname($this->logPath)) )
178
+ {
179
+ file_put_contents($this->logPath,$line, FILE_APPEND);
180
+ }
181
+ else {
182
+ error_log($line);
183
+ }
184
+ }
185
+
186
+ protected function formatLine($args = array() )
187
+ {
188
+ $line= $this->format;
189
+ foreach($args as $key => $value)
190
+ {
191
+ if (! is_array($value) && ! is_object($value))
192
+ $line = str_replace('%%' . $key . '%%', $value, $line);
193
+ }
194
+
195
+ $line .= PHP_EOL;
196
+
197
+ if (isset($args['data']))
198
+ {
199
+ $data = array_filter($args['data']);
200
+ if (count($data) > 0)
201
+ {
202
+ foreach($data as $item)
203
+ {
204
+ $line .= $item . PHP_EOL;
205
+ }
206
+ }
207
+ }
208
+
209
+ return $line;
210
+ }
211
+
212
+ protected function setLogLevel($level)
213
+ {
214
+ $this->logLevel = $level;
215
+ }
216
+
217
+ protected function getEnv($name)
218
+ {
219
+ if (isset($this->{$name}))
220
+ {
221
+ return $this->{$name};
222
+ }
223
+ else {
224
+ return false;
225
+ }
226
+ }
227
+
228
+ public static function addError($message, $args = array())
229
+ {
230
+ $level = DebugItem::LEVEL_ERROR;
231
+ $log = self::getInstance();
232
+ $log->addLog($message, $level, $args);
233
+ }
234
+ public static function addWarn($message, $args = array())
235
+ {
236
+ $level = DebugItem::LEVEL_WARN;
237
+ $log = self::getInstance();
238
+ $log->addLog($message, $level, $args);
239
+ }
240
+ public static function addInfo($message, $args = array())
241
+ {
242
+ $level = DebugItem::LEVEL_INFO;
243
+ $log = self::getInstance();
244
+ $log->addLog($message, $level, $args);
245
+ }
246
+ public static function addDebug($message, $args = array())
247
+ {
248
+ $level = DebugItem::LEVEL_DEBUG;
249
+ $log = self::getInstance();
250
+ $log->addLog($message, $level, $args);
251
+ }
252
+
253
+ public static function logLevel($level)
254
+ {
255
+ $log = self::getInstance();
256
+ static::addInfo('Changing Log level' . $level);
257
+ $log->setLogLevel($level);
258
+ }
259
+
260
+ public static function getLogLevel()
261
+ {
262
+ $log = self::getInstance();
263
+ return $log->getEnv('logLevel');
264
+ }
265
+
266
+ public static function isManualDebug()
267
+ {
268
+ $log = self::getInstance();
269
+ return $log->getEnv('is_manual_request');
270
+ }
271
+
272
+ public static function getLogPath()
273
+ {
274
+ $log = self::getInstance();
275
+ return $log->getEnv('logPath');
276
+ }
277
+
278
+ /** Function to test if the debugger is active
279
+ * @return boolean true when active.
280
+ */
281
+ public static function debugIsActive()
282
+ {
283
+ $log = self::getInstance();
284
+ return $log->getEnv('is_active');
285
+ }
286
+
287
+ protected function monitorHooks()
288
+ {
289
+
290
+ foreach($this->hooks as $hook => $data)
291
+ {
292
+ $numargs = isset($data['numargs']) ? $data['numargs'] : 1;
293
+ $prio = isset($data['priority']) ? $data['priority'] : 10;
294
+
295
+ add_filter($hook, function($value) use ($hook) {
296
+ $args = func_get_args();
297
+ return $this->logHook($hook, $value, $args); }, $prio, $numargs);
298
+ }
299
+ }
300
+
301
+ public function logHook($hook, $value, $args)
302
+ {
303
+ array_shift($args);
304
+ self::addInfo('[Hook] - ' . $hook . ' with ' . var_export($value,true), $args);
305
+ return $value;
306
+ }
307
+
308
+ public function loadView()
309
+ {
310
+ // load either param or class template.
311
+ $template = $this->template;
312
+
313
+ $view = $this->view;
314
+ $view->namespace = $this->namespace;
315
+ $controller = $this;
316
+
317
+ $template_path = __DIR__ . '/' . $this->template . '.php';
318
+ if (file_exists($template_path))
319
+ {
320
+
321
+ include($template_path);
322
+ }
323
+ else {
324
+ self::addError("View $template could not be found in " . $template_path,
325
+ array('class' => get_class($this), 'req' => $_REQUEST));
326
+ }
327
+ }
328
+
329
+
330
+ } // class debugController
build/shortpixel/log/src/view-debug-box.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Debug Box to load Log File
3
+ namespace ReThumbAdvanced\ShortPixelLogger;
4
+ wp_enqueue_script( 'jquery-ui-draggable' );
5
+
6
+ ?>
7
+
8
+ <style>
9
+ .sp_debug_wrap
10
+ {
11
+ position: relative;
12
+ clear: both;
13
+ }
14
+ .sp_debug_box
15
+ {
16
+ position: absolute;
17
+ right: 0px;
18
+ top: 50px;
19
+ background-color: #fff;
20
+ width: 150px;
21
+ z-index: 1000000;
22
+ border: 1px solid #000;
23
+
24
+ }
25
+ .sp_debug_box .header
26
+ {
27
+ min-height: 10px;
28
+ background: #000;
29
+ color: #fff;
30
+ padding: 8px
31
+ }
32
+ .sp_debug_box .content_box
33
+ {
34
+ background: #ccc;
35
+ }
36
+ .content_box
37
+ {
38
+ padding: 8px;
39
+ }
40
+ </style>
41
+
42
+ <script language='javascript'>
43
+ jQuery(document).ready(function($)
44
+ {
45
+ $( ".sp_debug_box" ).draggable();
46
+
47
+ });
48
+ </script>
49
+
50
+
51
+ <div class='sp_debug_box'>
52
+ <div class='header'><?php echo $view->namespace ?> Debug Box </div>
53
+ <a target="_blank" href='<?php echo $view->logLink ?>'>Logfile</a>
54
+ <div class='content_box'>
55
+
56
+ </div>
57
+ </div>
build/shortpixel/notices/composer.json ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "shortpixel/notices",
3
+ "description": "ShortPixel WordPress Notice System",
4
+ "version": "1.3",
5
+ "type": "library",
6
+ "license": "MIT",
7
+ "authors": [
8
+ {
9
+ "name": "Bas",
10
+ "email": "bas@weblogmechanic.com"
11
+ }
12
+ ],
13
+ "minimum-stability": "dev",
14
+ "require": {
15
+ "shortpixel/log" : "1.1.*"
16
+ },
17
+ "repositories": [
18
+ {
19
+ "packagist.org": false,
20
+ "type": "path",
21
+ "url": "../modules/",
22
+ "options": {
23
+ "symlink": true
24
+ }
25
+ }
26
+ ],
27
+
28
+ "autoload": {
29
+ "psr-4": { "ShortPixel\\Notices\\" : "src" }
30
+ }
31
+ }
build/shortpixel/notices/src/NoticeController.php ADDED
@@ -0,0 +1,332 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace ReThumbAdvanced\Notices;
3
+ use ReThumbAdvanced\ShortPixelLogger\ShortPixelLogger as Log;
4
+
5
+ class NoticeController //extends ShortPixelController
6
+ {
7
+ protected static $notices = array();
8
+ protected static $instance = null;
9
+ protected static $cssHookLoaded = false; // prevent css output more than once.
10
+
11
+ protected $notice_displayed = array();
12
+
13
+ public $notice_count = 0;
14
+
15
+ protected $has_stored = false;
16
+
17
+ protected $notice_option = ''; // The wp_options name for notices here.
18
+
19
+ /** For backward compat. Never call constructor directly. */
20
+ public function __construct()
21
+ {
22
+ // $this->loadModel('notice');
23
+ $ns = __NAMESPACE__;
24
+ $ns = substr($ns, 0, strpos($ns, '\\')); // try to get first part of namespace
25
+ $this->notice_option = $ns . '-notices';
26
+
27
+ add_action('wp_ajax_' . $this->notice_option, array($this, 'ajax_action'));
28
+
29
+ $this->loadNotices();
30
+ //$this->loadConfig();
31
+ }
32
+
33
+ public static function getInstance()
34
+ {
35
+ if ( self::$instance === null)
36
+ {
37
+ self::$instance = new NoticeController();
38
+ }
39
+
40
+ return self::$instance;
41
+ }
42
+
43
+ /** Load Notices Config File, if any
44
+ *
45
+ * [ Future Use ]
46
+ */
47
+ public function loadConfig()
48
+ {
49
+ return;
50
+ if (file_exists('../notice_config.json'))
51
+ {
52
+ $config = file_get_contents('../notice_config.json');
53
+ $json_config = json_decode($config);
54
+ }
55
+ }
56
+
57
+ public function loadIcons($icons)
58
+ {
59
+ foreach($icons as $name => $icon)
60
+ NoticeModel::setIcon($name, $icon);
61
+ }
62
+
63
+
64
+ protected function loadNotices()
65
+ {
66
+ $notices = get_option($this->notice_option, false);
67
+ $cnotice = (is_array($notices)) ? count($notices) : 0;
68
+ if ($cnotice > 0)
69
+ Log::addDebug('Notice Control - #num notices' . $cnotice);
70
+
71
+ if ($notices !== false && is_array($notices))
72
+ {
73
+ self::$notices = $notices;
74
+ $this->has_stored = true;
75
+ }
76
+ else {
77
+ self::$notices = array();
78
+ $this->has_stored = false;
79
+ }
80
+ $this->countNotices();
81
+ }
82
+
83
+
84
+ protected function addNotice($message, $code, $unique)
85
+ {
86
+ $notice = new NoticeModel($message, $code);
87
+
88
+ if ($unique)
89
+ {
90
+ foreach(self::$notices as $nitem)
91
+ {
92
+ if ($nitem->message == $notice->message && $nitem->code == $notice->code) // same message.
93
+ return $notice; // return the notice with the same message.
94
+ }
95
+ }
96
+ self::$notices[] = $notice;
97
+ $this->countNotices();
98
+ Log::addDebug('Adding notice - ', $notice);
99
+ $this->update();
100
+ return $notice;
101
+ }
102
+
103
+ /** Update the notices to store, check what to remove, returns count. */
104
+ public function update()
105
+ {
106
+ if (! is_array(self::$notices) || count(self::$notices) == 0)
107
+ {
108
+ if ($this->has_stored)
109
+ delete_option($this->notice_option);
110
+
111
+ return 0;
112
+ }
113
+
114
+ $new_notices = array();
115
+ foreach(self::$notices as $item)
116
+ {
117
+ if (! $item->isDone() )
118
+ {
119
+ $new_notices[] = $item;
120
+ }
121
+ }
122
+
123
+ update_option($this->notice_option, $new_notices);
124
+ self::$notices = $new_notices;
125
+
126
+ return $this->countNotices();
127
+ }
128
+
129
+ public function countNotices()
130
+ {
131
+ $this->notice_count = count(self::$notices);
132
+ return $this->notice_count;
133
+ }
134
+
135
+
136
+ public function getNotices()
137
+ {
138
+ return self::$notices;
139
+ }
140
+
141
+ public function getNoticesForDisplay()
142
+ {
143
+ $newNotices = array();
144
+ foreach(self::$notices as $notice)
145
+ {
146
+ if ($notice->isDismissed()) // dismissed never displays.
147
+ continue;
148
+
149
+ if ($notice->isPersistent())
150
+ {
151
+ $id = $notice->getID();
152
+ if (! is_null($id) && ! in_array($id, $this->notice_displayed))
153
+ {
154
+ $notice->notice_action = $this->notice_option;
155
+ $newNotices[] = $notice;
156
+ $this->notice_displayed[] = $id;
157
+ }
158
+
159
+ }
160
+ else
161
+ $newNotices[] = $notice;
162
+
163
+
164
+ }
165
+ return $newNotices;
166
+ }
167
+
168
+
169
+ public function getNoticeByID($id)
170
+ {
171
+ foreach(self::$notices as $notice)
172
+ {
173
+ if ($notice->getID() == $id)
174
+ return $notice;
175
+ }
176
+
177
+ return false;
178
+ }
179
+
180
+ public static function removeNoticeByID($id)
181
+ {
182
+ $noticeController = self::getInstance();
183
+
184
+ for($i = 0; $i < count(self::$notices); $i++)
185
+ {
186
+ $item = self::$notices[$i];
187
+ if ($item->getID() == $id)
188
+ {
189
+ Log::addDebug('Removing notice with ID ' . $id);
190
+ unset(self::$notices[$i]);
191
+ }
192
+ //if ($notice_item )
193
+ }
194
+ $noticeController->update();
195
+ }
196
+
197
+ public function ajax_action()
198
+ {
199
+ $response = array('result' => false, 'reason' => '');
200
+
201
+ if ( wp_verify_nonce( $_POST['nonce'], 'dismiss') )
202
+ {
203
+ if ($_POST['plugin_action'] == 'dismiss')
204
+ {
205
+ $id = sanitize_text_field($_POST['id']);
206
+ $notice = $this->getNoticeByID($id);
207
+
208
+ if($notice)
209
+ {
210
+ $notice->dismiss();
211
+ $this->update();
212
+ $response['result'] = true;
213
+ }
214
+ else
215
+ {
216
+ Log::addError('Notice not found when dismissing -> ' . $id, self::$notices);
217
+ $response['result'] = ' Notice ' . $id . ' not found. ';
218
+ }
219
+
220
+ }
221
+
222
+ }
223
+ else
224
+ {
225
+ Log::addError('Wrong Nonce when dismissed notice. ');
226
+ $response['reason'] = 'wrong nonce';
227
+ }
228
+ wp_send_json($response);
229
+ }
230
+
231
+ /** Adds a notice, quick and fast method
232
+ * @param String $message The Message you want to notify
233
+ * @param Boolean $unique If unique, check to not repeat notice exact same text in notices. Discard if so
234
+ * @param int $code A value of messageType as defined in model
235
+ * @returm Object Instance of noticeModel
236
+ */
237
+
238
+ public static function addNormal($message, $unique = false)
239
+ {
240
+ $noticeController = self::getInstance();
241
+ $notice = $noticeController->addNotice($message, NoticeModel::NOTICE_NORMAL, $unique);
242
+ return $notice;
243
+
244
+ }
245
+
246
+ public static function addError($message, $unique = false)
247
+ {
248
+ $noticeController = self::getInstance();
249
+ $notice = $noticeController->addNotice($message, NoticeModel::NOTICE_ERROR, $unique);
250
+ return $notice;
251
+
252
+ }
253
+
254
+ public static function addWarning($message, $unique = false)
255
+ {
256
+ $noticeController = self::getInstance();
257
+ $notice = $noticeController->addNotice($message, NoticeModel::NOTICE_WARNING, $unique);
258
+ return $notice;
259
+ }
260
+
261
+ public static function addSuccess($message, $unique = false)
262
+ {
263
+ $noticeController = self::getInstance();
264
+ $notice = $noticeController->addNotice($message, NoticeModel::NOTICE_SUCCESS, $unique);
265
+ return $notice;
266
+
267
+ }
268
+
269
+ public static function makePersistent($notice, $key, $suppress = -1)
270
+ {
271
+ $noticeController = self::getInstance();
272
+ $existing = $noticeController->getNoticeByID($key);
273
+
274
+ // if this key already exists, don't allow the new notice to be entered into the array. Remove it since it's already created.
275
+ if ($existing)
276
+ {
277
+ for($i = 0; $i < count(self::$notices); $i++)
278
+ {
279
+ $item = self::$notices[$i];
280
+
281
+ if ($item->message == $notice->message && $item->getID() == null)
282
+ {
283
+ if ($item->message != $existing->message) // allow the persistent message to be updated, if something else is served on this ID
284
+ {
285
+ $existing->message = $item->message;
286
+ }
287
+ unset(self::$notices[$i]);
288
+ }
289
+ //if ($notice_item )
290
+ }
291
+ }
292
+ else
293
+ {
294
+ $notice->setPersistent($key, $suppress); // set this notice persistent.
295
+ }
296
+
297
+ $noticeController->update();
298
+ }
299
+
300
+ public function admin_notices()
301
+ {
302
+ if ($this->countNotices() > 0)
303
+ {
304
+ if (! self::$cssHookLoaded)
305
+ {
306
+ add_action('admin_print_footer_scripts', array($this, 'printNoticeStyle'));
307
+ self::$cssHookLoaded = true;
308
+ }
309
+ foreach($this->getNoticesForDisplay() as $notice)
310
+ {
311
+ echo $notice->getForDisplay();
312
+ }
313
+ }
314
+ $this->update(); // puts views, and updates
315
+ }
316
+
317
+
318
+ public function printNoticeStyle()
319
+ {
320
+ if (file_exists(__DIR__ . '/css/notices.css'))
321
+ {
322
+ echo '<style>' . file_get_contents(__DIR__ . '/css/notices.css') . '</style>';
323
+ }
324
+ else {
325
+ Log::addDebug('Notices : css/notices.css could not be loaded');
326
+ }
327
+ }
328
+
329
+
330
+
331
+
332
+ }
build/shortpixel/notices/src/NoticeModel.php ADDED
@@ -0,0 +1,191 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace ReThumbAdvanced\Notices;
3
+
4
+ class NoticeModel //extends ShortPixelModel
5
+ {
6
+ public $message; // The message we want to convey.
7
+ public $code;
8
+
9
+ private $id = null; // used for persistent messages.
10
+ protected $viewed = false; // was this notice viewed?
11
+ protected $is_persistent = false; // This is a fatal issue, display until something was fixed.
12
+ protected $is_dismissed = false; // for persistent notices,
13
+ protected $suppress_until = null;
14
+ protected $suppress_period = -1;
15
+ public $is_removable = true; // if removable, display a notice dialog with red X or so.
16
+ public $messageType = self::NOTICE_NORMAL;
17
+
18
+ public $notice_action; // empty unless for display. Ajax action to talk back to controller.
19
+
20
+ public static $icons = array();
21
+
22
+ const NOTICE_NORMAL = 1;
23
+ const NOTICE_ERROR = 2;
24
+ const NOTICE_SUCCESS = 3;
25
+ const NOTICE_WARNING = 4;
26
+
27
+ /** Use this model in conjunction with NoticeController, do not call directly */
28
+ public function __construct($message, $messageType = self::NOTICE_NORMAL)
29
+ {
30
+ $this->message = $message;
31
+ $this->messageType = $messageType;
32
+
33
+ }
34
+
35
+ public function isDone()
36
+ {
37
+ // check suppressed
38
+ if ($this->is_dismissed && ! is_null($this->suppress_until))
39
+ {
40
+ if (time() >= $this->suppress_until)
41
+ {
42
+ //Log::addDebug('')
43
+ $this->is_persistent = false; // unpersist, so it will be cleaned and dropped.
44
+
45
+ }
46
+ }
47
+
48
+ if ($this->viewed && ! $this->is_persistent)
49
+ return true;
50
+ else
51
+ return false;
52
+ }
53
+
54
+ public function getID()
55
+ {
56
+ return $this->id;
57
+ }
58
+
59
+ public function isPersistent()
60
+ {
61
+ return $this->is_persistent;
62
+ }
63
+
64
+ public function isDismissed()
65
+ {
66
+ return $this->is_dismissed;
67
+ }
68
+
69
+ public function dismiss()
70
+ {
71
+ $this->is_dismissed = true;
72
+ $this->suppress_until = time() + $this->suppress_period;
73
+ }
74
+
75
+ public function unDismiss()
76
+ {
77
+ $this->is_dismissed = false;
78
+ }
79
+
80
+ public function setDismissedUntil($timestamp)
81
+ {
82
+ $this->suppress_until = $timestamp;
83
+ }
84
+
85
+
86
+ /** Set a notice persistent. Meaning it shows every page load until dismissed.
87
+ * @param $key Unique Key of this message. Required
88
+ * @param $suppress When dismissed do not show this message again for X amount of time. When -1 it will just be dropped from the Notices and not suppressed
89
+ */
90
+ public function setPersistent($key, $suppress = -1)
91
+ {
92
+ $this->id = $key;
93
+ $this->is_persistent = true;
94
+ $this->suppress_period = $suppress;
95
+ }
96
+
97
+ public static function setIcon($notice_type, $icon)
98
+ {
99
+ switch($notice_type)
100
+ {
101
+ case 'error':
102
+ $type = self::NOTICE_ERROR;
103
+ break;
104
+ case 'success':
105
+ $type = self::NOTICE_SUCCESS;
106
+ break;
107
+ case 'warning':
108
+ $type = self::NOTICE_WARNING;
109
+ break;
110
+ case 'normal':
111
+ default:
112
+ $type = self::NOTICE_NORMAL;
113
+ break;
114
+ }
115
+ self::$icons[$type] = $icon;
116
+ }
117
+
118
+ public function getForDisplay()
119
+ {
120
+ $this->viewed = true;
121
+ $class = 'shortpixel notice ';
122
+
123
+ $icon = '';
124
+
125
+ switch($this->messageType)
126
+ {
127
+ case self::NOTICE_ERROR:
128
+ $class .= 'notice-error ';
129
+ $icon = isset(self::$icons[self::NOTICE_ERROR]) ? self::$icons[self::NOTICE_ERROR] : '';
130
+ //$icon = 'scared';
131
+ break;
132
+ case self::NOTICE_SUCCESS:
133
+ $class .= 'notice-success ';
134
+ $icon = isset(self::$icons[self::NOTICE_SUCCESS]) ? self::$icons[self::NOTICE_SUCCESS] : '';
135
+ break;
136
+ case self::NOTICE_WARNING:
137
+ $class .= 'notice-warning ';
138
+ $icon = isset(self::$icons[self::NOTICE_WARNING]) ? self::$icons[self::NOTICE_WARNING] : '';
139
+ break;
140
+ case self::NOTICE_NORMAL:
141
+ $class .= 'notice-info ';
142
+ $icon = isset(self::$icons[self::NOTICE_NORMAL]) ? self::$icons[self::NOTICE_NORMAL] : '';
143
+ break;
144
+ default:
145
+ $class .= 'notice-info ';
146
+ $icon = '';
147
+ break;
148
+ }
149
+
150
+
151
+ if ($this->is_removable)
152
+ {
153
+ $class .= 'is-dismissible ';
154
+ }
155
+
156
+ if ($this->is_persistent)
157
+ {
158
+ $class .= 'is-persistent ';
159
+ }
160
+
161
+ $id = ! is_null($this->id) ? 'id="' . $this->id . '"' : '';
162
+
163
+ $output = "<div $id class='$class'><span class='icon'> " . $icon . "</span> <span class='content'>" . $this->message . "</span></div>";
164
+ if ($this->is_persistent && $this->is_removable)
165
+ {
166
+ $output .= "<script type='text/javascript'>\n" . $this->getDismissJS() . "\n</script>";
167
+ }
168
+ return $output;
169
+
170
+ }
171
+
172
+ private function getDismissJS()
173
+ {
174
+ $url = wp_json_encode(admin_url('admin-ajax.php'));
175
+ // $action = 'dismiss';
176
+ $nonce = wp_create_nonce('dismiss');
177
+
178
+ $data = wp_json_encode(array('action' => $this->notice_action, 'plugin_action' => 'dismiss', 'nonce' => $nonce, 'id' => $this->id, 'time' => $this->suppress_period));
179
+
180
+ // $data_string = "{action:'$this->notice_action'}";
181
+
182
+ $js = "jQuery(document).on('click','#$this->id button',
183
+ function() {
184
+ var data = $data;
185
+ var url = $url;
186
+ jQuery.post(url, data); }
187
+ );";
188
+ return "\n jQuery(document).ready(function(){ \n" . $js . "\n});";
189
+ }
190
+
191
+ }
build/shortpixel/notices/src/css/notices.css ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .shortpixel.notice {
2
+ padding: 8px; }
3
+ .shortpixel.notice img {
4
+ display: inline-block;
5
+ margin: 0 25px 0 0;
6
+ max-height: 50px; }
7
+ .shortpixel.notice .notice-dismiss {
8
+ margin-top: 10px; }
9
+
10
+ /* In-view notice ( not on top, between the options ) - styled after WP notice */
11
+ .view-notice {
12
+ box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1);
13
+ border: 4px solid #fff;
14
+ padding: 1px 12px; }
15
+ .view-notice p {
16
+ margin: 1em 0 !important; }
17
+ .view-notice.warning {
18
+ border-left-color: #ffb900; }
19
+
20
+ .view-notice-row {
21
+ display: none; }
build/shortpixel/notices/src/css/notices.scss ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ .shortpixel.notice
3
+ {
4
+ //padding: 18px;
5
+ //min-height: 50px;
6
+ padding: 8px;
7
+ img
8
+ {
9
+ display:inline-block;
10
+ margin: 0 25px 0 0;
11
+ max-height: 50px;
12
+ }
13
+ .notice-dismiss
14
+ {
15
+ margin-top: 10px;
16
+ }
17
+ }
18
+
19
+ /* In-view notice ( not on top, between the options ) - styled after WP notice */
20
+ .view-notice
21
+ {
22
+
23
+ box-shadow: 0 1px 1px 0 rgba( 0, 0, 0, 0.1 );
24
+ border: 4px solid #fff;
25
+
26
+ padding: 1px 12px;
27
+ p {
28
+ margin: 1em 0 !important;
29
+ }
30
+ &.warning
31
+ {
32
+ border-left-color: #ffb900;
33
+ }
34
+ }
35
+
36
+ .view-notice-row
37
+ {
38
+ display: none;
39
+ }
classes/controllers/rta_admin_controller.php ADDED
@@ -0,0 +1,264 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace ReThumbAdvanced;
3
+
4
+ class rtaAdminController extends rtaController
5
+ {
6
+ protected $controller;
7
+
8
+ /** Settings saved in the option table. Being set on construct. Refreshed on save */
9
+ protected $custom_image_sizes = array();
10
+ protected $process_image_sizes = false;
11
+ protected $process_image_options = array();
12
+ protected $system_image_sizes = array();
13
+ protected $jpeg_quality = 90;
14
+
15
+ protected $cropOptions;
16
+
17
+ public function __construct($controller)
18
+ {
19
+ wp_enqueue_style( 'rta_css_admin');
20
+ wp_enqueue_style( 'rta_css_admin_progress');
21
+
22
+ $this->controller = $controller;
23
+
24
+ $this->cropOptions = array(
25
+ 'no_cropped' => __('No','regenerate-thumbnails-advanced'),
26
+ 'cropped' => __('Yes','regenerate-thumbnails-advanced'),
27
+ 'left_top' => __('Left top','regenerate-thumbnails-advanced'),
28
+ 'left_center' => __('Left center','regenerate-thumbnails-advanced'),
29
+ 'left_bottom' => __('Left bottom','regenerate-thumbnails-advanced'),
30
+ 'center_top' => __('Center top','regenerate-thumbnails-advanced'),
31
+ 'center_center' => __('Center center','regenerate-thumbnails-advanced'),
32
+ 'center_bottom' => __('Center bottom','regenerate-thumbnails-advanced'),
33
+ 'right_top' => __('Right top','regenerate-thumbnails-advanced'),
34
+ 'right_center' => __('Right center','regenerate-thumbnails-advanced'),
35
+ 'right_bottom' => __('Right bottom','regenerate-thumbnails-advanced'),
36
+ );
37
+
38
+ $this->setOptionData();
39
+
40
+ }
41
+
42
+ protected function setOptionData()
43
+ {
44
+ $options = get_option('rta_image_sizes', $this->getDefaultOptions() );
45
+
46
+ if (isset($options['image_sizes']) && is_array($options['image_sizes']))
47
+ $this->custom_image_sizes = $options['image_sizes'];
48
+
49
+ if (isset($options['jpeg_quality']))
50
+ $this->jpeg_quality = $options['jpeg_quality'];
51
+
52
+ if (isset($options['process_image_sizes']) && is_array($options['process_image_sizes']))
53
+ $this->process_image_sizes = $options['process_image_sizes'];
54
+ else
55
+ $this->process_image_sizes = array();
56
+
57
+
58
+ if (isset($options['process_image_options']) && is_array($options['process_image_options']) )
59
+ $this->process_image_options = $options['process_image_options'];
60
+ else
61
+ $this->process_image_options = array();
62
+
63
+ $this->system_image_sizes = $this->getImageSizes();
64
+ }
65
+
66
+ private function getDefaultOptions()
67
+ {
68
+ $standard_sizes = array( 'thumbnail', 'medium', 'medium_large', 'large' ); // directly from media.php, hardcoded there.
69
+ $process_image_options = array();
70
+ foreach($standard_sizes as $name)
71
+ {
72
+ $process_image_options[$name] = array('overwrite_files' => false);
73
+ }
74
+ $options = array();
75
+ $options['process_image_sizes'] = $standard_sizes;
76
+ $options['process_image_options'] = $process_image_options;
77
+
78
+ return $options;
79
+ }
80
+
81
+ public function show()
82
+ {
83
+ $html = $this->load_template( "rta_generate_thumbnails", "admin", array('view' => $this) );
84
+ echo $html;
85
+ }
86
+
87
+ public function loadChildTemplate($name)
88
+ {
89
+ $html = $this->load_template($name, 'admin', array('view' => $this ));
90
+ echo $html;
91
+ }
92
+
93
+ /** Generate cropOptions
94
+ *
95
+ */
96
+ public function cropOptions($current = '')
97
+ {
98
+ $output = '';
99
+ foreach($this->cropOptions as $name => $label)
100
+ {
101
+ $selected = ($name == $current) ? 'selected' : '';
102
+ $output .= "<option value='$name' $selected>$label</option>";
103
+ }
104
+
105
+ return $output;
106
+ }
107
+
108
+ public function __get($name)
109
+ {
110
+ if (isset($this->{$name}))
111
+ {
112
+ return $this->{$name};
113
+ }
114
+ return false;
115
+ }
116
+
117
+ /** Save thumbnail settings.
118
+ *
119
+ * @return JSON Returns json result data
120
+ */
121
+ public function save_image_sizes() {
122
+ global $_wp_additional_image_sizes;
123
+
124
+ $jsonReponse = array('message' => '', 'error' => '');
125
+ $error = false;
126
+ $rta_image_sizes = array();
127
+ $option = array();
128
+ $exclude = array();
129
+
130
+ $nonce = isset($_POST['save_nonce']) ? $_POST['save_nonce'] : false;
131
+ if (! wp_verify_nonce($nonce, 'rta_save_image_sizes'))
132
+ {
133
+ $jsonResponse['error'] = 'Invalid Nonce';
134
+ return $jsonResponse;
135
+ }
136
+
137
+ if (isset($_POST['saveform']))
138
+ parse_str($_POST['saveform'], $formpost);
139
+ else
140
+ $formpost = array();
141
+
142
+ $image_sizes = isset($formpost['image_sizes']) ? $formpost['image_sizes'] : array();
143
+ $jpeg_quality = isset( $formpost['jpeg_quality']) ? $formpost['jpeg_quality'] : 0;
144
+
145
+ if (isset($image_sizes['name']))
146
+ {
147
+ for($i =0; $i < count($image_sizes['name']); $i++)
148
+ {
149
+ if (strlen($image_sizes['name'][$i]) <= 0)
150
+ {
151
+ continue;
152
+ }
153
+ // sanitize!
154
+ $rta_image_sizes['name'][] = isset($image_sizes['name'][$i]) ? sanitize_text_field($image_sizes['name'][$i]) : '';
155
+ $rta_image_sizes['pname'][] = isset($image_sizes['pname'][$i]) ? sanitize_text_field($image_sizes['pname'][$i]) : '';
156
+ $rta_image_sizes['width'][] = isset($image_sizes['width'][$i]) ? intval($image_sizes['width'][$i]) : '';
157
+ $rta_image_sizes['height'][] = isset($image_sizes['height'][$i]) ? intval($image_sizes['height'][$i]) : '';
158
+ $rta_image_sizes['cropping'][] = isset($image_sizes['cropping'][$i]) ? sanitize_text_field($image_sizes['cropping'][$i]) : '';
159
+ }
160
+
161
+ }
162
+
163
+ if ($jpeg_quality > 0)
164
+ $option['jpeg_quality'] = $jpeg_quality;
165
+
166
+ $option['image_sizes'] = $rta_image_sizes;
167
+
168
+ // redo the thumbnail options, apply changes
169
+ $sizes = isset($formpost['regenerate_sizes']) ? $formpost['regenerate_sizes'] : array();
170
+ $size_options = array();
171
+ foreach($sizes as $rsize)
172
+ {
173
+ if (isset($formpost['keep_' . $rsize]))
174
+ {
175
+ $size_options[$rsize] = array('overwrite_files' => false);
176
+ }
177
+ else {
178
+ $size_options[$rsize] = array('overwrite_files' => true);
179
+ }
180
+ }
181
+ $option['process_image_sizes'] = array_values($sizes); // the once that are set to regen. Array values resets index
182
+ $option['process_image_options'] = $size_options;
183
+
184
+ update_option( 'rta_image_sizes', $option );
185
+ $this->setOptionData();
186
+
187
+ $newsizes = $this->generateImageSizeOptions($sizes);
188
+ $jsonResponse = array( 'error' => $error, 'message' => '', 'new_image_sizes' => $newsizes );
189
+
190
+ return $jsonResponse;
191
+
192
+ }
193
+
194
+ /** Returns system wide defined image sizes plus our custom sizes
195
+ *
196
+ *
197
+ */
198
+ public function getImageSizes()
199
+ {
200
+ global $_wp_additional_image_sizes;
201
+
202
+ $option = get_option('rta_image_sizes');
203
+ $our_image_sizes = isset($option['image_sizes']) ? $option['image_sizes']: array();
204
+
205
+ $imageSizes = array();
206
+ foreach ( get_intermediate_image_sizes() as $_size )
207
+ {
208
+ if ( strpos($_size, 'rta_') === false)
209
+ $imageSizes[$_size] = $_size;
210
+ }
211
+
212
+ // put our defined images manually, to properly update when sizes /names change.
213
+ if (isset($our_image_sizes['pname']))
214
+ {
215
+ for($i = 0; $i < count($our_image_sizes['pname']); $i++ )
216
+ {
217
+ $int_name = $our_image_sizes['name'][$i];
218
+ $name = $our_image_sizes['pname'][$i];
219
+ if (strlen($name) == 0) // can't since name is tied to what it gives back to the process
220
+ $name = $int_name;
221
+
222
+ $imageSizes[$int_name] = $name;
223
+ }
224
+ }
225
+ return $imageSizes;
226
+
227
+ }
228
+
229
+ public function generateImageSizeOptions($checked_ar = false)
230
+ {
231
+ $output = '';
232
+ $i = 0;
233
+ $check_all = ($checked_ar === false) ? true : false;
234
+
235
+ $process_options = $this->process_image_options;
236
+
237
+ // size here is a name, value is how the name is found in the system (in interface, the technical name)
238
+ foreach($this->getImageSizes() as $value => $size):
239
+
240
+ //if ($check_all)
241
+ //$checked = 'checked';
242
+ $checked = ($check_all || in_array($value, $checked_ar)) ? 'checked' : '';
243
+ $hidden = ($checked == 'checked') ? '' : 'hidden'; // hide add. option if not checked.
244
+
245
+ $option_in_db = (isset($process_options[$value])) ? true : false;
246
+ $checked_keep = (isset($process_options[$value]) && isset($process_options[$value]['overwrite_files']) && ! $process_options[$value]['overwrite_files'] ) ? 'checked' : '';
247
+
248
+ if ($option_in_db)
249
+ $checked .= ' data-setbyuser=true'; // if value was ever saved in DB, don't change it in the JS.
250
+
251
+ $output .= "<div class='item'>";
252
+ $output .= "<span>
253
+ <label> <input type='checkbox' id='regenerate_sizes[$i]' name='regenerate_sizes[$i]' value='$value' $checked>
254
+ " . ucfirst($size) . "</label>
255
+ </span>";
256
+ $output .= "<span class='options $hidden'><label><input value='1' type='checkbox' $checked_keep name='keep_" . $value . "'> " . __('Don\'t redo existing', 'regenerate-thumbnails-advanced') . "</label></span>";
257
+ $output .= "</div>";
258
+
259
+ $i++;
260
+ endforeach;
261
+ return $output;
262
+ }
263
+
264
+ } // class
classes/rta-plugin.php ADDED
@@ -0,0 +1,227 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace ReThumbAdvanced;
3
+ use \ReThumbAdvanced\ShortPixelLogger\ShortPixelLogger as Log;
4
+ use \ReThumbAdvanced\Notices\NoticeController as Notice;
5
+
6
+
7
+ // load runtime.
8
+ class rtaPlugin
9
+ {
10
+
11
+ protected $paths = array('classes', 'classes/controllers');
12
+
13
+ protected $front;
14
+ protected $admin;
15
+
16
+ public function __construct()
17
+ {
18
+ $log = Log::getInstance();
19
+ if (Log::debugIsActive()) // upload dir can be expensive, so only do this when log is actually active.
20
+ {
21
+ $uploaddir =wp_upload_dir();
22
+ if (isset($uploaddir['basedir']))
23
+ $log->setLogPath($uploaddir['basedir'] . "/rta_log");
24
+ }
25
+ $this->initRuntime();
26
+
27
+ add_action( 'after_setup_theme', array( $this, 'add_custom_sizes' ) );
28
+ add_action( 'init', array( $this, 'init' ) );
29
+ add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ), 10 );
30
+
31
+ add_action( 'admin_menu', array( $this, 'admin_menus' ) );
32
+
33
+ add_filter( 'plugin_action_links_' . plugin_basename(RTA_PLUGIN_FILE), array($this, 'generate_plugin_links'));//for plugin settings page
34
+
35
+ }
36
+
37
+ public function initRuntime()
38
+ {
39
+ // $plugin_path = plugin_dir_path(SHORTPIXEL_PLUGIN_FILE);
40
+ foreach($this->paths as $short_path)
41
+ {
42
+ $directory_path = realpath(RTA_PLUGIN_PATH . $short_path);
43
+
44
+ if ($directory_path !== false)
45
+ {
46
+ $it = new \DirectoryIterator($directory_path);
47
+ foreach($it as $file)
48
+ {
49
+ $file_path = $file->getRealPath();
50
+ if ($file->isFile() && pathinfo($file_path, PATHINFO_EXTENSION) == 'php')
51
+ {
52
+ require_once($file_path);
53
+ }
54
+ }
55
+ }
56
+ }
57
+ }
58
+
59
+ // load textdomain, init.
60
+ public function init()
61
+ {
62
+ load_plugin_textdomain( 'regenerate-thumbnails-advanced', FALSE, RTA_LANG_DIR );
63
+
64
+ $this->front = new RTA_Front();
65
+ $this->admin = new RTA_Admin();
66
+
67
+ //add_action( 'admin_menu', array( $this, 'rta_admin_menus' ) );
68
+ add_action( 'wp_ajax_rta_regenerate_thumbnails', array( $this->admin, 'ajax_regenerate_thumbnails') );
69
+ add_action( 'wp_ajax_rta_start_regenerate', array($this->admin, 'ajax_start_process') );
70
+ add_action( 'wp_ajax_rta_stop_process', array($this->admin, 'ajax_rta_stop_process'));
71
+
72
+ //add_filter( 'image_size_names_choose', array( $this, 'rta_image_custom_sizes' ), 10, 1 );
73
+ add_action( 'wp_ajax_rta_save_image_sizes', array($this->admin,'view_generate_thumbnails_save' ) );
74
+
75
+ add_filter('media_row_actions', array($this,'add_media_action'), 10, 2);
76
+ add_action( 'add_meta_boxes', function () { add_meta_box('rta-link', __('Regenerate Thumbnails', 'enable-media-replace'), array($this, 'regenerate_meta_box'), 'attachment', 'side', 'low'); } );
77
+
78
+ $this->check_media_action();
79
+ //add_action('upload.php', array($this, 'check_media_action'), 10);
80
+
81
+ $notices = Notice::getInstance();
82
+
83
+ // Enqueue notices
84
+ add_action('admin_notices', array($notices, 'admin_notices')); // previous page / init time
85
+ add_action('admin_footer', array($notices, 'admin_notices')); // fresh notices between init - end
86
+
87
+ }
88
+
89
+ public function check_media_action()
90
+ {
91
+ if (isset($_GET['regen_action']) && $_GET['regen_action'] == 'regenerate_image_thumbnail')
92
+ {
93
+ $attach_id = intval($_GET['attachment_id']);
94
+ if (! wp_verify_nonce($_GET['_wpnonce'], 'regenerate_image_thumbnail'))
95
+ {
96
+ Notice::addError(__('Incorrect nonce','regenerate-thumbnails-advanced'));
97
+ }
98
+ elseif ($attach_id <= 0)
99
+ {
100
+ Notice::addError(__('No Attachment ID found, not regenerating','regenerate-thumbnails-advanced'));
101
+ }
102
+ else {
103
+ $result = $this->admin->regenerate_single_image($attach_id);
104
+
105
+ }
106
+
107
+ $sendback = remove_query_arg( array('attachment_id', 'regen_action', '_wpnonce') );
108
+ // exit($sendback);
109
+ wp_redirect($sendback);
110
+ exit();
111
+
112
+ }
113
+
114
+ }
115
+
116
+ // Registering styles and scripts.
117
+ public function enqueue_scripts() {
118
+
119
+ //wp_enqueue_script( 'jquery' );
120
+ wp_register_script( 'rta_js', RTA_PLUGIN_URL.'js/rta.js', array( 'jquery' ), RTA_PLUGIN_VERSION );
121
+ wp_register_style( 'rta_css', RTA_PLUGIN_URL.'css/rta.css', array(), RTA_PLUGIN_VERSION );
122
+ wp_register_style( 'rta_css_admin', RTA_PLUGIN_URL.'css/rta-admin-view.css', array(), RTA_PLUGIN_VERSION );
123
+ wp_register_style( 'rta_css_admin_progress', RTA_PLUGIN_URL.'css/rta-admin-progress.css', array('rta_css_admin'), RTA_PLUGIN_VERSION );
124
+
125
+
126
+ wp_localize_script( 'rta_js', 'rta_data', array(
127
+ 'ajaxurl' => admin_url( 'admin-ajax.php' ),
128
+ 'nonce_savesizes' => wp_create_nonce('rta_save_image_sizes'),
129
+ 'nonce_generate' => wp_create_nonce('rta_regenerate_thumbnails'),
130
+ 'strings' => array(
131
+ 'confirm_delete' => __('Are you sure you want to delete this image size?', 'regenerate-thumbnails-advanced'),
132
+ 'confirm_stop' => __("This will stop the regeneration process. You want to stop?", 'regenerate-thumbnails-advanced' ),
133
+ 'status_resume' => __("Interrupted process resumed", 'regenerate-thumbnails-advanced'),
134
+ 'status_start' => __('New Process started', 'regenerate-thumbnails-advanced'),
135
+ 'status_finish' => __('Process finished','regenerate-thumbnails-advanced' ),
136
+ ),
137
+ 'blog_id' => get_current_blog_id(),
138
+ 'process' => $this->admin->get_json_process(),
139
+ ));
140
+
141
+ do_action('rta_enqueue_scripts');
142
+ }
143
+
144
+ // add admin pages
145
+ public function admin_menus(){
146
+ $title = __('Regenerate Thumbnails', 'regenerate-thumbnails-advanced');
147
+ add_management_page($title, $title, 'manage_options', 'rta_generate_thumbnails', array($this, 'view_generate_thumbnails' ));
148
+ }
149
+
150
+ // filter for plugin page.
151
+ public function generate_plugin_links($links) {
152
+ $in = '<a href="tools.php?page=rta_generate_thumbnails">' . __('Settings', 'regenerate-thumbnails-advanced') . '</a>';
153
+ array_unshift($links, $in);
154
+ return $links;
155
+ }
156
+
157
+ public function view_generate_thumbnails() {
158
+ wp_enqueue_style('rta_css');
159
+ wp_enqueue_script('rta_js');
160
+ //$rta_image_sizes = get_option( 'rta_image_sizes' );
161
+ $view = new rtaAdminController($this);
162
+ $view->show();
163
+ }
164
+
165
+ public function add_custom_sizes() {
166
+
167
+ $rta_image_sizes = get_option( 'rta_image_sizes', false);
168
+ if (! $rta_image_sizes)
169
+ return $rta_image_sizes;
170
+
171
+ $image_sizes = isset($rta_image_sizes['image_sizes']) && is_array($rta_image_sizes['image_sizes']) ? $rta_image_sizes['image_sizes'] : array();
172
+
173
+ if(count($image_sizes) > 0 && count($image_sizes['name']) > 0){
174
+ for($i=0;$i<sizeof($image_sizes['name']);$i++){
175
+ $crop = false;
176
+ if($image_sizes['cropping'][$i]=='no_cropped'){
177
+ $crop = false;
178
+ }elseif($image_sizes['cropping'][$i]=='cropped') {
179
+ $crop = true;
180
+ }else{
181
+ $crop = explode("_", $image_sizes['cropping'][$i]);
182
+ }
183
+ add_image_size( $image_sizes['name'][$i], $image_sizes['width'][$i], $image_sizes['height'][$i], $crop );
184
+ }
185
+ }
186
+ }
187
+
188
+ private function getRegenerateLink()
189
+ {
190
+ // $url = admin_url( "upload.php");
191
+
192
+ }
193
+
194
+ public function add_media_action( $actions, $post) {
195
+
196
+ $action = 'regenerate_image_thumbnail';
197
+
198
+ $url = add_query_arg(array(
199
+ 'regen_action' => $action,
200
+ 'attachment_id' => $post->ID,
201
+ ));
202
+
203
+
204
+ $editurl = wp_nonce_url( $url, $action );
205
+ $link = "href=\"$editurl\"";
206
+
207
+ $newaction[$action] = '<a ' . $link . ' aria-label="' . esc_attr(__("Regenerate Thumbnails", "regenerate-thumbnails-advanced")) . '" rel="permalink">' . esc_html(__("Regenerate Thumbnails", "regenerate-thumbnails-advanced")) . '</a>';
208
+
209
+ return array_merge($actions,$newaction);
210
+ }
211
+
212
+ public function regenerate_meta_box($post)
213
+ {
214
+ $action = 'regenerate_image_thumbnail';
215
+
216
+ $url = add_query_arg(array(
217
+ 'regen_action' => $action,
218
+ 'attachment_id' => $post->ID,
219
+ ));
220
+
221
+ $editurl = wp_nonce_url( $url, $action );
222
+ $link = "href=\"$editurl\"";
223
+
224
+ echo "<p><a class='button-secondary' $link>" . esc_html__("Regenerate Thumbnails", "regenerate-thumbnails-advanced") . "</a></p>";
225
+ }
226
+
227
+ }
classes/rta_admin.php ADDED
@@ -0,0 +1,695 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace ReThumbAdvanced;
3
+ use \ReThumbAdvanced\ShortPixelLogger\ShortPixelLogger as Log;
4
+ use \ReThumbAdvanced\Notices\NoticeController as Notice;
5
+
6
+ /**
7
+ * Class that will hold functionality for admin side
8
+ *
9
+ * PHP version 5
10
+ *
11
+ * @category Admin Side Code
12
+ * @package Regenerate Thumbnails Advanced
13
+ * @author ShortPixel
14
+ */
15
+
16
+ class RTA_Admin extends rtaController
17
+ {
18
+ const PERIOD_ALL = 0;
19
+ const PERIOD_DAY = 1;
20
+ const PERIOD_WEEK = 2;
21
+ const PERIOD_MONTH = 3;
22
+ const PERIOD_3MONTH = 4;
23
+ const PERIOD_6MONTH = 5;
24
+ const PERIOD_YEAR = 6;
25
+
26
+ protected $viewControl = null; // controller that handles the admin page.
27
+
28
+ private $process_remove_thumbnails = false;
29
+ private $process_delete_leftmetadata = false;
30
+ private $process_cleanup_metadata = false;
31
+
32
+ private $process;
33
+ private $currentImage;
34
+ private $image_posts_to_delete = array();
35
+
36
+ //Admin side starting point. Will call appropriate admin side hooks
37
+ public function __construct() {
38
+ $this->customThumbSuffixes = array('_c', '_tl', '_tr', '_br', '_bl');
39
+
40
+ // do_action('rta_before_admin', $this );
41
+ //All admin side code will go here
42
+ $this->process = $this->get_process();
43
+ if ($this->process === false) // no saved state.
44
+ {
45
+ $process = new \stdClass; // format of process.
46
+ $process->total = 0;
47
+ $process->current = 0;
48
+ $process->formData = null;
49
+ $process->running = false;
50
+ $process->status = array(); //array('error' => false, 'status' => null, 'message' => null);
51
+
52
+ $this->process = $process;
53
+ }
54
+ //add_filter( 'plugin_action_links_' . plugin_basename(RTA_PLUGIN_FILE), array($this, 'generate_plugin_links'));//for plugin settings page
55
+
56
+ // do_action('rta_after_admin', $this );
57
+ }
58
+
59
+
60
+ /**
61
+ * schedules the image's attachment post to be deleted if all the thumbnails are missing or just removes the missing thumbnails from the sizes array if some still are present.
62
+ * @param $image_id
63
+ * TODO Remove this pass by reference.
64
+ */
65
+ /*function rta_del_leftover_metadata($image_id, $fullsizepath) {
66
+ $original_meta = wp_get_attachment_metadata($image_id);
67
+ $allSizesMissing = true;
68
+ $someSizesMissing = false;
69
+ if(isset($original_meta['sizes']) && is_array($original_meta['sizes'])) {
70
+ foreach ($original_meta['sizes'] as $key => $size) {
71
+ if(isset($size['file'])) {
72
+ $thumb = (is_array($size['file'])) ? $size['file'][0] : $size['file'];
73
+ if(file_exists(trailingslashit(dirname($fullsizepath)) . $thumb)) {
74
+ $allSizesMissing = false;
75
+ } else {
76
+ unset($original_meta['sizes'][$key]);
77
+ $someSizesMissing = true;
78
+ }
79
+ }
80
+ }
81
+ }
82
+ if($allSizesMissing) {
83
+ $this->image_posts_to_delete[] = $image_id;
84
+ } elseif($someSizesMissing) {
85
+ wp_update_attachment_metadata($image_id, $original_meta);
86
+ }
87
+ } */
88
+
89
+ public function regenerate_single_image($attach_id)
90
+ {
91
+ $form = $this->getFormData();
92
+ $form['posts_per_page'] = -1;
93
+ $form['attach_id'] = $attach_id;
94
+
95
+ if ($this->start_process($form))
96
+ {
97
+ $this->regenerate_thumbnails();
98
+ }
99
+
100
+ foreach($this->process->status as $statusName => $statusItem)
101
+ {
102
+ if ($statusItem['error'])
103
+ Notice::addError($statusItem['message']);
104
+ elseif ($statusItem['status'] == 1)
105
+ Notice::addSuccess(__('Image thumbnails regenerated', 'regenerate-thumbnails-advanced'));
106
+ else
107
+ Notice::addNormal($statusItem['message']);
108
+ }
109
+
110
+ $this->end_process();
111
+ }
112
+
113
+ public function getQueryDate($period)
114
+ {
115
+ $date = false;
116
+ $args = false;
117
+ switch (intval($period)) {
118
+ case self::PERIOD_ALL:
119
+ break;
120
+ case self::PERIOD_DAY:
121
+ $date = '-1 day';
122
+ $args = array('after' => '1 day ago', 'before' => 'tomorrow');
123
+ break;
124
+ case self::PERIOD_WEEK:
125
+ $date = '-1 week';
126
+ $args = array('after' => '1 week ago', 'before' => 'tomorrow');
127
+ break;
128
+ case self::PERIOD_MONTH:
129
+ $date = '-1 month';
130
+ $args = array('after' => '1 month ago', 'before' => 'tomorrow');
131
+ break;
132
+ case self::PERIOD_3MONTH:
133
+ $date = '-3 month';
134
+ $args = array('after' => '3 months ago', 'before' => 'tomorrow');
135
+ break;
136
+ case self::PERIOD_6MONTH:
137
+ $date = '-6 month';
138
+ $args = array('after' => '6 months ago', 'before' => 'tomorrow');
139
+ break;
140
+ case self::PERIOD_YEAR:
141
+ $date = '-1 year';
142
+ $args = array('after' => '1 year ago', 'before' => 'tomorrow');
143
+ break;
144
+ }
145
+ $result = array('date' => $date, 'args' => $args);
146
+ return $result;
147
+ }
148
+
149
+ public function getThumbQueryArgs($data, $posts_per_page, $offset)
150
+ {
151
+
152
+ $query_args = array(
153
+ 'post_type' => 'attachment',
154
+ // 'post_mime_type' => 'image', // @todo Crashed images can have no mime_type.
155
+ 'posts_per_page' => $posts_per_page,
156
+ 'post_status' => 'any',
157
+ 'offset' => $offset,
158
+ );
159
+
160
+ if (isset($data['period'])) {
161
+ $period = intval($data['period']);
162
+ $date_query = $this->getQueryDate($period);
163
+
164
+ if (is_array($date_query['args']))
165
+ {
166
+ $query_args['date_query'] = $date_query['args'];
167
+ }
168
+ }
169
+
170
+ if ($data['regenonly_featured'])
171
+ {
172
+ global $wpdb;
173
+ $meta_query_args = array(
174
+ array(
175
+ 'key' => '_thumbnail_id',
176
+ 'compare' => 'IN',
177
+ ),
178
+ );
179
+
180
+ $sql = ' SELECT meta_value from ' . $wpdb->postmeta . ' where meta_key = "_thumbnail_id"';
181
+ $result = $wpdb->get_col($sql);
182
+
183
+ if (count($result) > 0)
184
+ $query_args['post__in'] = array_values($result);
185
+
186
+ if (count($result) === 0)
187
+ return false; // no thumbnails, nothing to process
188
+ }
189
+
190
+ if (isset($data['attach_id']))
191
+ {
192
+ $query_args['p'] = $data['attach_id'];
193
+ }
194
+
195
+ return $query_args;
196
+ }
197
+
198
+ /** Collect form data, make a storable process array out of it */
199
+ public function getFormData()
200
+ {
201
+ $defaults = array(
202
+ 'period' => self::PERIOD_ALL,
203
+ 'regenonly_featured' => false,
204
+ 'del_associated_thumbs' => false,
205
+ 'del_leftover_metadata' => false,
206
+ 'process_clean_metadata' => false,
207
+ );
208
+
209
+ $data = array();
210
+ $form = isset($_POST['genform']) ? $_POST['genform'] : '';
211
+ parse_str($form, $data);
212
+
213
+ return wp_parse_args($data, $defaults);
214
+ }
215
+
216
+ // Seperate function for ajax, to clean main function clean of json and exists.
217
+ public function ajax_start_process()
218
+ {
219
+ if (isset($_POST['genform']))
220
+ {
221
+ $form = $this->getFormData();
222
+ }
223
+ else {
224
+ // $this->jsonResponse(array('error' => true, 'logstatus' => __("No Form Data was send", 'message' => "Site error, No Data"));
225
+ exit();
226
+ }
227
+
228
+ $nonce = isset($_POST['gen_nonce']) ? $_POST['gen_nonce'] : false;
229
+ if (! wp_verify_nonce($nonce, 'rta_regenerate_thumbnails'))
230
+ {
231
+ $this->add_status('no_nonce');
232
+ $this->jsonResponse($this->get_json_process());
233
+ exit();
234
+ }
235
+
236
+ $result = $this->start_process($form);
237
+ $this->jsonResponse($this->get_json_process());
238
+
239
+ exit();
240
+
241
+ }
242
+
243
+ /** Starts a new generate process. Queries the totals based on form input
244
+ * @param $form Array with FormData
245
+ * @return boolean true if all went ok, false if error occured
246
+ * Status and errors can be gotten from process attribute.
247
+ */
248
+ public function start_process($form)
249
+ {
250
+
251
+ $posts_per_page = -1; // all
252
+ $offset = 0; // all
253
+
254
+ // $post_count = 0;
255
+ /* $process = new \stdClass;
256
+ $process->total = 0;
257
+ $process->current = 0; */
258
+ $this->process->formData = $form;
259
+ $this->process->current = 0;
260
+
261
+ Log::addDebug('Start Process FormData', $form);
262
+ $query_args = $this->getThumbQueryArgs($form, $posts_per_page, $offset);
263
+
264
+ if ($query_args === false) // zero result situation.
265
+ {
266
+ $this->add_status('no_images');
267
+ $this->end_process();
268
+ return false;
269
+ }
270
+
271
+ $the_query = new \WP_Query($query_args);
272
+
273
+
274
+ Log::addDebug('Start Process Start with args', $query_args);
275
+ $count = $the_query->found_posts;
276
+ $this->process->total = $count;
277
+
278
+ if ($count == 0)
279
+ {
280
+ $this->add_status('no_images');
281
+ $this->end_process();
282
+ return false;
283
+ }
284
+
285
+
286
+ wp_reset_query();
287
+ wp_reset_postdata();
288
+
289
+ // This is something legacy . @todo remove at some point.
290
+ delete_option('rta_get_all_files');
291
+
292
+ $this->save_process($this->process);
293
+ return true;
294
+
295
+ }
296
+
297
+ protected function save_process($process)
298
+ {
299
+ $p = clone $process; // passed by reference, want to keep it in current scope.
300
+ unset($p->status); // don't save status.
301
+ update_option('rta_image_process', $p, false);
302
+ }
303
+
304
+ protected function get_process()
305
+ {
306
+ $process = get_option('rta_image_process', false);
307
+ if (! is_object($process))
308
+ return false;
309
+
310
+ $process->status = array(); // process is saved without it.
311
+ if ($process->current == $process->total)
312
+ {
313
+ return false; // don't consider a done process a process
314
+ }
315
+ return $process; // if false, no process running. If object, running process there.
316
+ }
317
+
318
+ protected function end_process()
319
+ {
320
+ $this->process->running = false;
321
+ delete_option('rta_image_process');
322
+ }
323
+
324
+ // retrieve JS friendly overview, if we are in process and if yes, what are we doing here.
325
+ public function get_json_process()
326
+ {
327
+ //$json = array('running' => false);
328
+
329
+ $json['running'] = $this->process->running;
330
+ $json['current'] = $this->process->current;
331
+ $json['total'] = $this->process->total;
332
+ $json['status'] = $this->process->status;
333
+ return $json;
334
+ }
335
+
336
+ protected function add_status($name, $args = array() )
337
+ {
338
+ $status = array('error' => true, 'message' => __('Unknown Error occured', 'regenerate-thumbnails-advanced'), 'status' => 0);
339
+
340
+ switch($name)
341
+ {
342
+ case 'no_nonce':
343
+ $status['message'] = __('Site error, Invalid Nonce', 'regenerate-thumbnails-advanced');
344
+ $status['status'] = -1;
345
+ break;
346
+
347
+ case 'no_images':
348
+ $status['message'] = __('No images found for this period and/or settings or none uploaded', 'regenerate-thumbnails-advanced');
349
+ $status['status'] = 0;
350
+ $status['error'] = false;
351
+ break;
352
+ case 'file_missing':
353
+ $name = isset($args['name']) ? $args['name'] : '';
354
+ $status['message'] = __(sprintf('<b>%s</b> is missing or not an image file',$name), 'regenerate-thumbnails-advanced');
355
+ $status['status'] = -2;
356
+ break;
357
+ case 'error_metadata':
358
+ $name = isset($args['name']) ? $args['name'] : '';
359
+ $status['message'] = __(sprintf('<b>%s</b> failed on metadata. Possible issue with image',$name), 'regenerate-thumbnails-advanced');
360
+ $status['status'] = -3;
361
+ break;
362
+ case 'request_stop':
363
+ $status['message'] = __('Process stopped on request', 'regenerate-thumbnails-advanced');
364
+ $status['status'] = -4;
365
+ break;
366
+ case 'regenerate_success':
367
+ $thumb = isset($args['thumb']) ? $args['thumb'] : '';
368
+ $status['message'] = $thumb;
369
+ $status['status'] = 1;
370
+ $status['error'] = false;
371
+ break;
372
+
373
+ }
374
+
375
+
376
+ $this->process->status[] = $status;
377
+ }
378
+
379
+ // generate thumbnails. @todo Update process, so it does it by 5 or so images, not the one-by-one boredom.
380
+ public function regenerate_thumbnails() {
381
+
382
+ $form = $this->process->formData;
383
+ $this->process->running = true;
384
+
385
+ $del_thumbs = isset($form['del_associated_thumbs']) ? $form['del_associated_thumbs'] : false;
386
+ $del_leftover_metadata = isset($form['del_leftover_metadata']) ? $form['del_leftover_metadata'] : false;
387
+
388
+ $this->process_remove_thumbnails = $del_thumbs;
389
+ $this->process_delete_leftmetadata = $del_leftover_metadata;
390
+ $this->process_clean_metadata = isset($form['process_clean_metadata']) ? $form['process_clean_metadata'] : false;
391
+
392
+ $has_period = (isset($form['period']) && $form['period'] > 0) ? true : false;
393
+ //$is_featured_only = (isset($data['regenonly_featured']) ) ? true : false;
394
+
395
+ //$process_type = (isset($_POST['type'])) ? sanitize_text_field($_POST['type']) : false;
396
+ $period = isset($form['period']) ? intval($form['period']) : -1;
397
+
398
+ $posts_per_page = apply_filters('rta/process/per_page', $form['posts_per_page']) ;
399
+ $offset = isset($_POST['offset']) ? intval($_POST['offset']) : 0;
400
+
401
+ $query_args = $this->getThumbQueryArgs($form, $posts_per_page, $offset);
402
+
403
+ $imageUrl='';
404
+ $error = array();
405
+
406
+ $bulk = ($period == 0) ? true : false;
407
+
408
+ $this->viewControl = new rtaAdminController($this);
409
+
410
+ $the_query = new \WP_Query($query_args);
411
+ $last_success_url = false;
412
+
413
+ if ($the_query->have_posts()) {
414
+
415
+
416
+ // The process runs just 1 image per run here.
417
+ while ($the_query->have_posts()) {
418
+ $the_query->the_post();
419
+ $image_id = $the_query->post->ID;
420
+
421
+ Log::addDebug('Next Item in process ' . $image_id);
422
+
423
+ // simplification
424
+ $this->currentImage = new rtaImage($image_id);
425
+ $fullsizepath = $this->currentImage->getPath();
426
+
427
+ if ($this->process_remove_thumbnails)
428
+ {
429
+ $this->currentImage->setCleanUp(true);
430
+ Log::addDebug('Image thumbnails will be cleaned');
431
+ }
432
+
433
+ /* if ($this->process_delete_leftmetadata)
434
+ {
435
+ $this->currentImage->setMetaCheck(true);
436
+ Log::addDebug('Image Metadata Thumbs will be checked');
437
+ } */
438
+
439
+ // If Image doesn't exist at all, remove all metadata.
440
+ if($this->process_delete_leftmetadata && ! $this->currentImage->exists() ) { // !file_exists($fullsizepath) )
441
+ //$this->rta_del_leftover_metadata($image_id, $fullsizepath);
442
+ $this->image_posts_to_delete[] = $image_id;
443
+ // Log::addDebug('Image did not exist. Removing leftover metadata');
444
+ }
445
+
446
+ if (isset($data['mediaID'])){
447
+ $image_id = intval($data['mediaID']);
448
+ }
449
+
450
+ $filename_only = $this->currentImage->getUri(); //wp_get_attachment_thumb_url($image_id);
451
+
452
+ if ($this->currentImage->isImage() ) {
453
+
454
+ @set_time_limit(900);
455
+ do_action('shortpixel-thumbnails-before-regenerate', $image_id);
456
+
457
+ //use the original main image if exists
458
+ $backup = apply_filters('shortpixel_get_backup', $fullsizepath);
459
+ if($backup && $backup !== $fullsizepath) {
460
+ Log::addDebug('Retrieving SPIO backups for process');
461
+ copy($fullsizepath, $backup . "_optimized_" . $image_id);
462
+ copy($backup, $fullsizepath);
463
+ }
464
+
465
+ add_filter('intermediate_image_sizes_advanced', array($this, 'capture_generate_sizes'));
466
+ // RTA should never touch source files. This happens when redoing scaling. This would also be problematic in combination with optmisers. Disable scaling when doing thumbs.
467
+ add_filter('big_image_size_threshold', array($this, 'disable_scaling'));
468
+
469
+ $new_metadata = wp_generate_attachment_metadata($image_id, $fullsizepath);
470
+
471
+ remove_filter('intermediate_image_sizes_advanced', array($this, 'capture_generate_sizes'));
472
+ remove_filter('big_image_size_threshold', array($this, 'disable_scaling'));
473
+
474
+ Log::addDebug('New Attachment metadata generated');
475
+ //restore the optimized main image
476
+ if($backup && $backup !== $fullsizepath) {
477
+ rename($backup . "_optimized_" . $image_id, $fullsizepath);
478
+ }
479
+
480
+ //get the attachment name
481
+ if (is_wp_error($new_metadata)) {
482
+ /* $error[] = array('offset' => ($offset + 1), 'error' => $error, 'logstatus' => $logstatus, 'imgUrl' => $filename_only, 'period' => $period); */
483
+ $this->add_status('error_metadata', array('name' => basename($filename_only) ));
484
+ }
485
+ else if (empty($new_metadata)) {
486
+ $filename_only = $this->currentImage->getUri();
487
+ // $logstatus = '<b>'.basename($filename_only).'</b> is missing';
488
+ Log::addDebug('File missing - New metadata returned empty', array($new_metadata, $filename_only,$fullsizepath ));
489
+ $this->add_status('file_missing', array('name' => basename($filename_only) ));
490
+ /*$error[] = array('offset' => ($offset + 1), 'error' => $error, 'logstatus' => $logstatus, 'imgUrl' => $filename_only, 'period' => $period); */
491
+ } else {
492
+
493
+ // going for the save.
494
+ $original_meta = $this->currentImage->getMetaData();
495
+ $result = $this->currentImage->saveNewMeta($new_metadata); // this here calls the regeneration.
496
+ Log::addDebug('Result :', $result);
497
+
498
+ $is_a_bulk = true; // we are sending multiple images.
499
+ $regenSizes = isset($new_metadata['sizes']) ? $new_metadata['sizes'] : array();
500
+
501
+ // Do not send if nothing was regenerated, otherwise SP thinks all needs to be redone
502
+ if (count($regenSizes) > 0)
503
+ {
504
+ do_action('shortpixel-thumbnails-regenerated', $image_id, $original_meta, $regenSizes, $is_a_bulk);
505
+ }
506
+ $last_success_url = $filename_only;
507
+
508
+ }
509
+ $imageUrl = $filename_only;
510
+ //$logstatus = 'Processed';
511
+ $filename_only = wp_get_attachment_thumb_url($image_id);
512
+ } else {
513
+ $filename_only = $this->currentImage->getUri();
514
+ //$logstatus = '<b>'.basename($filename_only).'</b> is missing or not an image file';
515
+ Log::addDebug('File missing - Current Image reported as not an image', array($fullsizepath) );
516
+ $this->add_status('file_missing', array('name' => basename($filename_only)) );
517
+
518
+ /*$error[] = array('offset' => ($offset + 1), 'error' => $error, 'logstatus' => $logstatus, 'imgUrl' => $filename_only, 'startTime' => $data['startTime'], 'fromTo' => $data['fromTo'], 'type' => $process_type, 'period' => $period); */
519
+ }
520
+
521
+ $this->process->current++;
522
+ $this->save_process($this->process);
523
+
524
+ } // Post Loop
525
+
526
+
527
+ foreach($this->image_posts_to_delete as $to_delete) {
528
+ Log::addDebug('Deleting post ' . $to_delete);
529
+ wp_delete_post($to_delete, true);
530
+ }
531
+ }
532
+
533
+ // @todo move this to view maybe? Test maybe via WP function
534
+ if (!extension_loaded('gd') && !function_exists('gd_info')) {
535
+ $filename_only = 'No file';
536
+ $logstatus = 'PHP GD library is not installed on your web server. Please install in order to have the ability to resize and crop images';
537
+ $error[] = array('offset' => ($offset + 1), 'error' => $error, 'logstatus' => $logstatus, 'imgUrl' => $filename_only, 'period' => $period);
538
+ }
539
+ //increment offset
540
+ // $result = $offset + 1;
541
+ if(!isset($filename_only)){
542
+ $filename_only = 'No files';
543
+ }
544
+ Log::addDebug($error);
545
+ //$finalResult = array('offset' => ($offset + 1), 'error' => $error, 'logstatus' => $logstatus, 'imgUrl' => $filename_only, 'startTime' => $data['startTime'], 'fromTo' => $data['fromTo'], 'period' => $period);
546
+
547
+ if ($last_success_url) // if anything was done good, return last regenerated thumb.
548
+ $this->add_status('regenerate_success', array('thumb' => $last_success_url));
549
+
550
+ return true;
551
+ }
552
+
553
+ public function ajax_regenerate_thumbnails()
554
+ {
555
+ $nonce = isset($_POST['gen_nonce'])? $_POST['gen_nonce'] : false;
556
+ if (! wp_verify_nonce($nonce, 'rta_regenerate_thumbnails'))
557
+ {
558
+ $this->add_status('no_nonce');
559
+ $this->jsonResponse($this->get_json_process());
560
+ exit();
561
+ }
562
+
563
+ $result = $this->regenerate_thumbnails();
564
+ $this->jsonResponse($this->get_json_process());
565
+ exit();
566
+ }
567
+
568
+ public function ajax_rta_stop_process()
569
+ {
570
+ $nonce = isset($_POST['gen_nonce'])? $_POST['gen_nonce'] : false;
571
+ if (! wp_verify_nonce($nonce, 'rta_regenerate_thumbnails'))
572
+ {
573
+ $this->add_status('no_nonce');
574
+ $this->jsonResponse($this->get_json_process());
575
+ exit();
576
+ }
577
+
578
+ $this->process = $this->get_process();
579
+ $this->end_process();
580
+ $this->add_status('request_stop');
581
+
582
+ $this->jsonResponse($this->get_json_process());
583
+ exit();
584
+
585
+ }
586
+
587
+ public function disable_scaling()
588
+ {
589
+ return false;
590
+ }
591
+
592
+ public function capture_generate_sizes($full_sizes)
593
+ {
594
+ $do_regenerate_sizes = $this->viewControl->process_image_sizes; // to images to be regenerated.
595
+ $process_options = $this->viewControl->process_image_options; // the setting options for each size.
596
+
597
+ // imageMetaSizes is sizeName => Data based array of WP metadata.
598
+ $imageMetaSizes = $this->currentImage->getCurrentSizes();
599
+
600
+ $prevent_regen = array();
601
+ foreach($do_regenerate_sizes as $rsize)
602
+ {
603
+ // 1. Check if size exists, if not, needs generation anyhow.
604
+ if (! isset($imageMetaSizes[$rsize]))
605
+ {
606
+ Log::addDebug("Image Meta size setting missing - $rsize ");
607
+ continue;
608
+ }
609
+
610
+ // 2. Check meta info (file) from the current meta info we have.
611
+ $metaSize = $imageMetaSizes[$rsize];
612
+ $overwrite = isset($process_options[$rsize]['overwrite_files']) ? $process_options[$rsize]['overwrite_files'] : false; // 3. Check if we keep or overwrite.
613
+
614
+ if (! $overwrite)
615
+ {
616
+ // thumbFile is RELATIVE. So find dir via main image.
617
+ $thumbFile = $this->currentImage->getDir() . $metaSize['file'];
618
+ //Log::addDebug('Preventing overwrite of - ' . $thumbFile);
619
+ if (file_exists($thumbFile)) // 4. Check if file is really there
620
+ {
621
+ $prevent_regen[] = $rsize;
622
+ // Add to current Image the metaSize since it will be dropped by the metadata redoing.
623
+ Log::addDebug('File exists on ' . $rsize . ' ' . $thumbFile . ' - skipping regen - prevent overwrite');
624
+ $this->currentImage->addPersistentMeta($rsize, $metaSize);
625
+ }
626
+ }
627
+ }
628
+
629
+
630
+ // 5. Drop the 'not to be' regen. images from the sizes so it will not process.
631
+ $do_regenerate_sizes = array_diff($do_regenerate_sizes, $prevent_regen);
632
+ Log::addDebug('Sizes going for regen - ', $do_regenerate_sizes);
633
+
634
+ /* 6. If metadata should be cleansed of undefined sizes, remove them from the imageMetaSizes
635
+ * This is for sizes that are -undefined- in total by system sizes.
636
+ */
637
+ if ($this->process_clean_metadata)
638
+ {
639
+ $system_sizes = $this->viewControl->system_image_sizes;
640
+
641
+ $not_in_system = array_diff( array_keys($imageMetaSizes), array_keys($system_sizes) );
642
+ if (count($not_in_system) > 0)
643
+ Log::addDebug('Cleaning not in system', $not_in_system);
644
+
645
+ foreach($not_in_system as $index => $unset)
646
+ {
647
+ unset($imageMetaSizes[$unset]);
648
+ }
649
+ }
650
+
651
+ // 7. If unused thumbnails are not set for delete, keep the metadata intact.
652
+ if (! $this->process_remove_thumbnails)
653
+ {
654
+ $other_meta = array_diff( array_keys($imageMetaSizes), $do_regenerate_sizes, $prevent_regen);
655
+ if (count($other_meta) > 0)
656
+ Log::addDebug('Image sizes not selected, but not up for deletion', $other_meta);
657
+
658
+ foreach($other_meta as $size)
659
+ {
660
+ if (isset($imageMetaSizes[$size]))
661
+ $this->currentImage->addPersistentMeta($size, $imageMetaSizes[$size]);
662
+ }
663
+ }
664
+
665
+ $returned_sizes = array();
666
+ foreach($full_sizes as $key => $data)
667
+ {
668
+ if (in_array($key, $do_regenerate_sizes))
669
+ {
670
+ $returned_sizes[$key] = $data;
671
+ }
672
+ }
673
+
674
+ $this->currentImage->setRegeneratedSizes($do_regenerate_sizes);
675
+ return $returned_sizes;
676
+ }
677
+
678
+ /* Saves and generates JSON response */
679
+ public function view_generate_thumbnails_save()
680
+ {
681
+ $json = true;
682
+ $view = new rtaAdminController($this);
683
+ $response = $view->save_image_sizes();
684
+
685
+ if ($json)
686
+ {
687
+ $this->jsonResponse($response);
688
+ }
689
+ else
690
+ {
691
+ return $response;
692
+ }
693
+ }
694
+
695
+ } // Class
classes/rta_controller.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace ReThumbAdvanced;
3
+
4
+
5
+ // Main Controller
6
+ class rtaController
7
+ {
8
+
9
+ /** Central function for JSON responses. Can be extended whenever needed */
10
+ protected function jsonResponse($response)
11
+ {
12
+ wp_send_json($response);
13
+ }
14
+
15
+ /** @todo not sur why this is such a complicated function */
16
+ public function load_template( $template='', $for='front', $attr=array() ) {
17
+
18
+ do_action( 'rta_before_load_template', $template, $for, $attr );
19
+ $template = apply_filters( 'rta_template_to_load', $template, $for, $attr );
20
+ $attr = apply_filters( 'rta_template_variables', $attr, $template, $for );
21
+
22
+ if( empty($template) ) {
23
+ return '';
24
+ }
25
+ if( is_array($attr) ) {
26
+ extract($attr);
27
+ }
28
+ $html = '';
29
+ $html = apply_filters( 'rta_before_template_html', $html, $template, $for, $attr );
30
+ ob_start();
31
+ require (RTA_PLUGIN_PATH.'templates/'.$for.'/'.$template.'.php');
32
+ $html = ob_get_contents();
33
+ ob_end_clean();
34
+
35
+ do_action( 'rta_after_load_template', $template, $for, $attr, $html );
36
+ $html = apply_filters( 'rta_after_template_html', $html, $template, $for, $attr );
37
+
38
+ return $html;
39
+ }
40
+ } // class
classes/rta_front.php ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace ReThumbAdvanced;
3
+ /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
+
5
+ /**
6
+ * Class that will hold functionality for front side
7
+ *
8
+ * PHP version 5
9
+ *
10
+ * @category Front Side Code
11
+ * @package Regenerate Thumbnails ID SCOUT
12
+ * @author Muhammad Atiq
13
+ * @version 1.0.0
14
+ * @since File available since Release 1.0.0
15
+ */
16
+
17
+ class RTA_Front
18
+ {
19
+ //Front side starting point. Will call appropriate front side hooks
20
+ public function __construct() {
21
+ //All front side code will go here
22
+ add_filter( 'image_size_names_choose', array( $this, 'rta_image_size_names_choose' ), 10, 1 );
23
+ add_filter( 'jpeg_quality', array( $this, 'rta_jpeg_quality' ),10, 1);
24
+ do_action('rta_after_front_init');
25
+ }
26
+
27
+ public function rta_jpeg_quality( $quality ) {
28
+ $rta_image_sizes = get_option( 'rta_image_sizes' );
29
+ if(is_array($rta_image_sizes) && sizeof($rta_image_sizes) > 0){
30
+ $jpeg_quality = isset($rta_image_sizes['jpeg_quality']) ? $rta_image_sizes['jpeg_quality'] : null;
31
+ if(!empty($jpeg_quality)) {
32
+ return (int)$jpeg_quality;
33
+ }
34
+ }
35
+ return $quality;
36
+ }
37
+
38
+ public function rta_image_size_names_choose( $sizes ) {
39
+
40
+ $rta_image_sizes = get_option( 'rta_image_sizes', false );
41
+ if (! $rta_image_sizes) // option not set
42
+ return $sizes;
43
+ if (! isset($rta_image_sizes['image_sizes']))
44
+ return $sizes;
45
+
46
+ $image_sizes = $rta_image_sizes['image_sizes'];
47
+
48
+ $rta_sizes = array();
49
+ if(is_array($image_sizes) && count($image_sizes) > 0 && sizeof($image_sizes['name']) > 0){
50
+ for($i=0;$i<sizeof($image_sizes['name']);$i++){
51
+ $slug = $image_sizes['name'][$i];
52
+ $name = $image_sizes['pname'][$i];
53
+ $rta_sizes[$slug] = $name;
54
+ }
55
+
56
+ }
57
+
58
+ $new_sizes = array_merge( $sizes, $rta_sizes );
59
+ return $new_sizes;
60
+ }
61
+
62
+
63
+ }
classes/rta_image.php CHANGED
@@ -1,4 +1,7 @@
1
  <?php
 
 
 
2
 
3
  class rtaImage
4
  {
@@ -7,6 +10,7 @@ class rtaImage
7
  protected $is_image = true;
8
  protected $does_exist = true;
9
  protected $do_cleanup =false;
 
10
 
11
  protected $filePath;
12
  protected $fileUri;
@@ -22,18 +26,31 @@ class rtaImage
22
  {
23
  $this->id = $image_id;
24
 
25
- $this->filePath = get_attached_file($image_id);
 
 
 
26
  $this->fileDir = trailingslashit(pathinfo($this->filePath, PATHINFO_DIRNAME));
27
- $this->fileUri = wp_get_attachment_thumb_url($image_id);
 
 
 
 
28
 
29
  if (!file_exists($this->filePath))
30
  $this->does_exist = false;
31
 
32
- if (! file_is_displayable_image($this->filePath))
33
  $this->is_image = false;
34
 
35
  $this->metadata = wp_get_attachment_metadata($image_id);
36
 
 
 
 
 
 
 
37
  }
38
 
39
  // Todo before doing this, function to remove thumbnails need to run somehow, without killing all.
@@ -61,6 +78,20 @@ class rtaImage
61
 
62
  $result = array();
63
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  $result['update'] = wp_update_attachment_metadata($this->id, $updated_meta);
65
  $this->metadata = wp_get_attachment_metadata($this->id);
66
 
@@ -73,7 +104,7 @@ class rtaImage
73
  }
74
 
75
  /** This function tries to find related thumbnails to the current image. If there are not in metadata after our process, assume cleanup.
76
- *
77
  * See ShortPixel Image Optimiser's findThumbs method
78
  **
79
  **/
@@ -191,5 +222,23 @@ class rtaImage
191
  $this->do_cleanup = $clean;
192
  }
193
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194
 
195
  }
1
  <?php
2
+ namespace ReThumbAdvanced;
3
+ use \ReThumbAdvanced\ShortPixelLogger\ShortPixelLogger as Log;
4
+
5
 
6
  class rtaImage
7
  {
10
  protected $is_image = true;
11
  protected $does_exist = true;
12
  protected $do_cleanup =false;
13
+ protected $do_metacheck = false;
14
 
15
  protected $filePath;
16
  protected $fileUri;
26
  {
27
  $this->id = $image_id;
28
 
29
+ if (function_exists('wp_get_original_image_path')) // WP 5.3+
30
+ $this->filePath = wp_get_original_image_path($image_id);
31
+ else
32
+ $this->filePath = get_attached_file($image_id);
33
  $this->fileDir = trailingslashit(pathinfo($this->filePath, PATHINFO_DIRNAME));
34
+
35
+ if (function_exists('wp_get_original_image_url')) // WP 5.3+
36
+ $this->fileUri = wp_get_original_image_url($image_id);
37
+ else
38
+ $this->fileUri = wp_get_attachment_url($image_id);
39
 
40
  if (!file_exists($this->filePath))
41
  $this->does_exist = false;
42
 
43
+ if (! file_is_displayable_image($this->filePath)) // this is based on getimagesize
44
  $this->is_image = false;
45
 
46
  $this->metadata = wp_get_attachment_metadata($image_id);
47
 
48
+ $is_image_mime = wp_attachment_is('image', $image_id); // this is based on post mime.
49
+ if (! $is_image_mime && $this->is_image )
50
+ {
51
+ $this->fixMimeType($image_id);
52
+ }
53
+
54
  }
55
 
56
  // Todo before doing this, function to remove thumbnails need to run somehow, without killing all.
78
 
79
  $result = array();
80
 
81
+ if ($this->do_metacheck && isset($updated_meta['sizes']))
82
+ {
83
+ Log::addDebug('Do metaCheck now for ' . $this->id);
84
+ foreach($updated_meta['sizes'] as $size => $sizedata)
85
+ {
86
+ $thumbfile = $this->getDir() . $sizedata['file'];
87
+ if (! file_exists($thumbfile))
88
+ {
89
+ Log::addDebug('Thumbfile not existing. Unsetting this size', array($size, $thumbfile, $this->id));
90
+ unset($updated_meta['sizes'][$size]);
91
+ }
92
+ }
93
+ }
94
+
95
  $result['update'] = wp_update_attachment_metadata($this->id, $updated_meta);
96
  $this->metadata = wp_get_attachment_metadata($this->id);
97
 
104
  }
105
 
106
  /** This function tries to find related thumbnails to the current image. If there are not in metadata after our process, assume cleanup.
107
+ * This removed thumbnail files.
108
  * See ShortPixel Image Optimiser's findThumbs method
109
  **
110
  **/
222
  $this->do_cleanup = $clean;
223
  }
224
 
225
+ public function setMetaCheck($bool)
226
+ {
227
+ $this->do_metacheck = $bool;
228
+ }
229
+
230
+ public function fixMimeType($image_id)
231
+ {
232
+ $post = get_post($image_id);
233
+
234
+ if ($post->post_mime_type == '')
235
+ {
236
+ $mime = wp_get_image_mime($this->filePath);
237
+ $post->post_mime_type = $mime;
238
+ Log::addDebug('Fixing File Mime for ' . $this->filePath . ' new MIME - ' . $mime);
239
+ wp_update_post($post);
240
+ }
241
+ }
242
+
243
 
244
  }
css/rta-admin-progress.css ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ section.regenerate {
2
+ background-color: #fff;
3
+ margin-bottom: 200px; }
4
+ section.regenerate .rta_panel_off {
5
+ opacity: 0;
6
+ transition: all 0ms linear; }
7
+ section.regenerate .rta_progress {
8
+ position: relative;
9
+ min-height: 310px;
10
+ width: 65%;
11
+ justify-content: flex-start; }
12
+ section.regenerate .rta_progress .rta_progress_view {
13
+ margin: 0 auto; }
14
+ section.regenerate .rta_progress .rta_progress_view svg.CircularProgressbar {
15
+ display: inline-block;
16
+ width: 200px;
17
+ padding: 25px 0; }
18
+ section.regenerate .rta_progress .rta_progress_view svg.CircularProgressbar .CircularProgressbar-trail {
19
+ stroke: #d6d6d6; }
20
+ section.regenerate .rta_progress .rta_progress_view svg.CircularProgressbar .CircularProgressbar-path {
21
+ stroke: #00bcd4;
22
+ stroke-linecap: round;
23
+ transition: stroke-dashoffset 0.5s ease 0s; }
24
+ section.regenerate .rta_progress .rta_progress_view svg.CircularProgressbar .CircularProgressbar-text {
25
+ fill: #00bcd4;
26
+ font-size: 20px;
27
+ dominant-baseline: middle;
28
+ text-anchor: middle; }
29
+ section.regenerate .rta_progress .rta_progress_view svg.CircularProgressbar .progress-count {
30
+ font-size: 9px;
31
+ font-weight: bold;
32
+ dominant-baseline: middle;
33
+ text-anchor: middle;
34
+ fill: 999; }
35
+ section.regenerate .rta_progress .images {
36
+ padding: 15px;
37
+ border-top: 1px solid #cecece;
38
+ border-bottom: 1px solid #cecece;
39
+ width: 60%; }
40
+ section.regenerate .rta_progress .images h5 {
41
+ text-align: center; }
42
+ section.regenerate .rta_progress .images .thumbnail {
43
+ text-align: center;
44
+ margin-top: 35px; }
45
+ section.regenerate .rta_progress .images .thumbnail img {
46
+ max-width: 500px;
47
+ max-height: 500px; }
48
+ section.regenerate .rta_status_box {
49
+ width: 35%;
50
+ border-left: 1px solid #ccc; }
51
+ section.regenerate .rta_status_box .rta_wait_loader {
52
+ margin-top: 35px;
53
+ padding-left: 20px;
54
+ opacity: 0; }
55
+ section.regenerate .rta_status_box .rta_wait_loader .dashicons {
56
+ animation: wait-spin 2000ms infinite linear;
57
+ width: 35px;
58
+ height: 35px;
59
+ font-size: 35px;
60
+ float: left;
61
+ margin-right: 30px; }
62
+ section.regenerate .rta_status_box .rta_notices ul.statuslist {
63
+ max-height: 350px;
64
+ overflow-y: auto;
65
+ overflow-x: visible;
66
+ margin-left: 15px; }
67
+ section.regenerate .rta_status_box .rta_notices ul.statuslist li {
68
+ font-size: 14px; }
69
+ section.regenerate .rta_status_box .rta_notices ul.statuslist li.error {
70
+ color: #ff0000; }
71
+ section.regenerate .rta_status_box h4 {
72
+ font-size: 22px;
73
+ font-weight: bold; }
74
+ @keyframes wait-spin {
75
+ 0% {
76
+ transform: rotate(0); }
77
+ 100% {
78
+ transform: rotate(360deg); } }
79
+ section.regenerate .rta_success_box {
80
+ position: absolute;
81
+ left: 30%;
82
+ top: -5%;
83
+ width: 45%;
84
+ margin-left: -200px;
85
+ opacity: 0.9;
86
+ background-color: #fff;
87
+ text-align: center;
88
+ padding: 15px;
89
+ border: 1px solid #00bcd4;
90
+ border-radius: 8px; }
91
+ section.regenerate .rta_success_box p {
92
+ font-size: 16px; }
93
+ section.regenerate .rta_success_box h3.header {
94
+ font-size: 32px;
95
+ font-weight: bold;
96
+ color: green; }
97
+ section.regenerate .rta_success_box .shortpixel h3 a {
98
+ line-height: 28px; }
99
+ section.regenerate .rta_success_box .modal-close {
100
+ position: absolute;
101
+ right: 15px;
102
+ top: 15px;
103
+ cursor: pointer; }
104
+ section.regenerate .rta_success_box .modal-close .dashicons {
105
+ font-size: 36px;
106
+ width: 36px;
107
+ height: 36px; }
108
+ section.regenerate .shortpixel-notice {
109
+ background: #fff;
110
+ width: 250px;
111
+ min-height: 270px;
112
+ border: 1px solid #ccc;
113
+ padding: 15px;
114
+ margin: 0 5% 10px 25px;
115
+ float: right; }
116
+ section.regenerate .shortpixel-notice h3 {
117
+ line-height: 1.3em; }
118
+ section.regenerate button.stop-process {
119
+ position: absolute;
120
+ bottom: 10px;
121
+ right: 15px;
122
+ font-weight: normal;
123
+ text-transform: none; }
css/rta-admin-view.css CHANGED
@@ -1,194 +1,207 @@
1
- .rta-admin {
2
- /*.rta_hidden
3
- {
4
- display: none !important;
5
- } */ }
6
- .rta-admin .two-panel-wrap {
7
- display: flex;
8
- justify-content: space-between; }
9
- @media (max-width: 1600px) {
10
- .rta-admin .two-panel-wrap {
11
- flex-direction: column-reverse; }
12
- .rta-admin .two-panel-wrap .rta-regenerate-wrap, .rta-admin .two-panel-wrap .rta-settings-wrap {
13
- width: 95%;
14
- max-width: none; } }
15
- .rta-admin h2 {
16
- font-size: 26px;
17
- padding-left: 8px; }
18
- .rta-admin h4 {
19
- font-size: 16px;
20
- margin: 8px 0 8px 15px; }
21
- .rta-admin form {
22
- min-height: 600px;
23
- padding-bottom: 65px; }
24
- .rta-admin .rta-regenerate-wrap, .rta-admin .rta-settings-wrap {
25
- flex: 1;
26
- margin-bottom: 20px;
27
- position: relative;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  padding: 0 15px;
29
- background: #fff; }
30
- .rta-admin .rta-regenerate-wrap {
31
- max-width: 35%; }
32
- .rta-admin .rta-settings-wrap {
33
- max-width: 60%; }
34
- .rta-admin button, .rta-admin .btn_add_more {
35
- color: white;
36
- background: #00bcd4;
37
- position: relative;
38
- box-shadow: none;
39
- cursor: pointer;
40
- border: 0;
41
- border-right: 1px solid #ccc;
42
- border-bottom: 1px solid #ccc;
43
- box-shadow: 0px 0px 4px #aaa; }
44
- .rta-admin .container {
45
- padding: 20px 8px;
46
- position: relative;
47
- margin: 0 auto; }
48
- .rta-admin .option {
49
- padding: 10px; }
50
- .rta-admin .option > label {
51
- width: 150px;
52
- display: inline-block;
53
- margin-right: 15px;
54
- padding: 0 15px;
55
- font-weight: bold;
56
- vertical-align: top;
57
- line-height: 15px; }
58
- .rta-admin .option .note {
59
- font-size: 12px;
60
- margin-left: 15px; }
61
- .rta-admin input.tiny {
62
- width: 65px; }
63
- .rta-admin button {
64
- font-size: 14px;
65
- text-transform: uppercase;
66
- font-weight: 700;
67
- margin: 0px;
68
- padding: 16px;
69
- border-radius: 4px; }
70
- .rta-admin button.disabled {
71
- background: #ccc;
72
- cursor: default;
73
- color: #eee; }
74
- .rta-admin .btn_add_more {
75
- font-size: 13px;
76
- padding: 5px 6px;
77
- margin-left: 25px; }
78
- .rta-admin .table {
79
- table-layout: fixed;
80
- display: table;
81
- border-spacing: 10px 0;
82
- border: 1px solid #eee;
83
- word-wrap: normal;
84
- white-space: nowrap; }
85
- .rta-admin .table .header, .rta-admin .table .row {
86
- width: 100%;
87
- display: table-row; }
88
- .rta-admin .table .header input.image_sizes_pname, .rta-admin .table .row input.image_sizes_pname {
89
- max-width: 180px; }
90
- .rta-admin .table .header span, .rta-admin .table .row span {
91
- display: table-cell;
92
- padding: 5px; }
93
- .rta-admin .table .row.proto, .rta-admin .table .rta_hidden {
94
- display: none; }
95
- .rta-admin .flex {
96
- display: flex; }
97
- .rta-admin .checkbox-list {
98
- display: inline-block; }
99
- .rta-admin .checkbox-list .item {
100
- display: flex;
101
- margin: 5px 0px;
102
- float: left;
103
- clear: both;
104
- justify-content: space-between;
105
- width: 100%; }
106
- .rta-admin .checkbox-list .item span {
107
- display: inline-block;
108
- margin-right: 14px; }
109
- .rta-admin .checkbox-list .item span.hidden {
110
- visibility: hidden; }
111
- .rta-admin .checkbox-list input {
112
- margin-right: 8px; }
113
- .rta-admin .select-options {
114
- margin-left: 200px;
115
- margin-top: 15px; }
116
- .rta-admin .select-options > span {
117
- cursor: pointer;
118
- color: #222;
119
- margin-right: 12px;
120
- display: inline-block; }
121
- .rta-admin .select-options .note {
122
- margin-left: 0;
123
- border: 1px solid #ccc;
124
- padding: 8px; }
125
- .rta-admin .cleanup-wrapper {
126
- padding: 8px;
127
- border: 1px solid #ddd; }
128
- .rta-admin .cleanup-wrapper .option {
129
- display: flex;
130
- flex: 1; }
131
- .rta-admin .cleanup-wrapper .option .note {
132
- flex: 2; }
133
- .rta-admin section.regenerate {
134
- background-color: #fff; }
135
- .rta-admin section.regenerate .CircularProgressbar {
136
  display: inline-block;
137
- width: 200px;
138
- padding: 25px 0; }
139
- .rta-admin section.regenerate .rta_progress {
 
140
  display: inline-block;
141
- position: relative;
142
- min-height: 310px; }
143
- .rta-admin section.regenerate .images {
144
- margin-left: 225px;
145
- float: left;
146
- padding: 15px;
147
- border: 1px solid #cecece;
148
- margin-right: 50px;
149
- opacity: 0; }
150
- .rta-admin section.regenerate .images h5 {
151
- text-align: center; }
152
- .rta-admin section.regenerate .images img {
153
- max-width: 500px;
154
- max-height: 500px; }
155
- .rta-admin section.regenerate .rta_hidden {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
  display: inline-block;
157
- display: none; }
158
- .rta-admin section.regenerate .shortpixel-notice {
159
- background: #fff;
160
- width: 250px;
161
- min-height: 270px;
162
- border: 1px solid #ccc;
163
- padding: 15px;
164
- margin: 0 5% 10px 25px;
165
- float: right; }
166
- .rta-admin section.regenerate .shortpixel-notice h3 {
167
- line-height: 1.3em; }
168
- .rta-admin section.regenerate .shortpixel-bulk-notice {
169
- font-size: 14px;
170
- font-weight: 700;
171
- text-align: center; }
172
- .rta-admin section.regenerate button.stop-process {
173
- position: absolute;
174
- bottom: 10px;
175
- left: 80%;
176
- font-weight: normal;
177
- text-transform: none; }
178
- .rta-admin .form_controls {
 
 
 
 
 
 
 
 
 
 
 
 
179
  position: absolute;
180
- left: 45px;
181
- bottom: 0px; }
182
- .rta-admin .form_controls .save_indicator {
183
- display: none;
184
- color: #049901;
185
- font-weight: 700;
186
- background: url("/wp-admin/images/wpspin_light.gif") no-repeat left center;
187
- background-size: 16px 16px;
188
- padding-left: 20px; }
189
- .rta-admin .form_controls .save_indicator .saved {
190
- font-size: 60px; }
191
- .rta-admin .form_controls .save_note {
192
- color: orange;
193
- float: right;
194
- margin-left: 30px; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .rta-admin .two-panel-wrap {
2
+ display: flex;
3
+ justify-content: space-between; }
4
+ @media (max-width: 1600px) {
5
+ .rta-admin .two-panel-wrap {
6
+ flex-direction: column-reverse; }
7
+ .rta-admin .two-panel-wrap .rta-settings-wrap {
8
+ width: 95%;
9
+ max-width: none; } }
10
+ .rta-admin h2 {
11
+ font-size: 26px;
12
+ padding-left: 8px; }
13
+ .rta-admin h4 {
14
+ font-size: 16px;
15
+ margin: 8px 0 8px 15px; }
16
+ .rta-admin form {
17
+ min-height: 600px;
18
+ padding-bottom: 65px; }
19
+ .rta-admin .rta-notice {
20
+ margin: 8px 0;
21
+ padding: 8px;
22
+ border-width: 1px;
23
+ border-style: solid;
24
+ transition: all 500ms ease-in; }
25
+ .rta-admin .rta-notice .icon {
26
+ font-size: 35px;
27
+ float: left;
28
+ display: inline-block;
29
+ width: auto;
30
+ height: auto; }
31
+ .rta-admin .rta-notice p {
32
+ font-size: 15px;
33
+ margin: 4px 0;
34
+ margin-left: 45px; }
35
+ .rta-admin .rta-notice p.small {
36
+ font-size: 0.8em; }
37
+ .rta-admin .rta-notice.warning {
38
+ border-color: #ffb900; }
39
+ .rta-admin .rta-notice.warning .icon {
40
+ color: #ffb900; }
41
+ .rta-admin .rta-notice.error {
42
+ border-color: #ff0000; }
43
+ .rta-admin .rta-regenerate-wrap, .rta-admin .rta-settings-wrap {
44
+ flex: 1;
45
+ margin-bottom: 20px;
46
+ position: relative;
47
+ padding: 0 15px;
48
+ background: #fff; }
49
+ .rta-admin .rta-regenerate-wrap {
50
+ max-width: 35%; }
51
+ .rta-admin .rta-settings-wrap {
52
+ max-width: 60%; }
53
+ .rta-admin button, .rta-admin .btn_add_more {
54
+ color: white;
55
+ background: #00bcd4;
56
+ position: relative;
57
+ box-shadow: none;
58
+ cursor: pointer;
59
+ border: 0;
60
+ border-right: 1px solid #ccc;
61
+ border-bottom: 1px solid #ccc;
62
+ box-shadow: 0px 0px 4px #aaa; }
63
+ .rta-admin .container {
64
+ padding: 20px 8px;
65
+ position: relative;
66
+ margin: 0 auto; }
67
+ .rta-admin .option {
68
+ padding: 10px; }
69
+ .rta-admin .option > label {
70
+ width: 150px;
71
+ display: inline-block;
72
+ margin-right: 15px;
73
  padding: 0 15px;
74
+ font-weight: bold;
75
+ vertical-align: top;
76
+ line-height: 15px;
77
+ position: relative; }
78
+ .rta-admin .option > label input {
79
+ vertical-align: middle;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  display: inline-block;
81
+ line-height: 35px;
82
+ position: absolute;
83
+ margin-top: 2px; }
84
+ .rta-admin .option > label span {
85
  display: inline-block;
86
+ margin-left: 25px; }
87
+ .rta-admin .option .note {
88
+ font-size: 12px;
89
+ margin-left: 15px; }
90
+ .rta-admin .option .note p {
91
+ margin-top: 0; }
92
+ .rta-admin input.tiny {
93
+ width: 65px; }
94
+ .rta-admin button {
95
+ font-size: 14px;
96
+ text-transform: uppercase;
97
+ font-weight: 700;
98
+ margin: 0px;
99
+ padding: 16px;
100
+ border-radius: 4px; }
101
+ .rta-admin button.disabled {
102
+ background: #ccc;
103
+ cursor: default;
104
+ color: #eee; }
105
+ .rta-admin .btn_add_more {
106
+ font-size: 13px;
107
+ padding: 5px 6px;
108
+ margin-left: 25px; }
109
+ .rta-admin .table {
110
+ table-layout: fixed;
111
+ display: table;
112
+ border-spacing: 10px 0;
113
+ border: 1px solid #eee;
114
+ word-wrap: normal;
115
+ white-space: nowrap; }
116
+ .rta-admin .table .header, .rta-admin .table .row {
117
+ width: 100%;
118
+ display: table-row; }
119
+ .rta-admin .table .header input.image_sizes_pname, .rta-admin .table .row input.image_sizes_pname {
120
+ max-width: 180px; }
121
+ .rta-admin .table .header span, .rta-admin .table .row span {
122
+ display: table-cell;
123
+ padding: 5px; }
124
+ .rta-admin .table .row.proto, .rta-admin .table .rta_hidden {
125
+ display: none; }
126
+ .rta-admin .flex {
127
+ display: flex; }
128
+ .rta-admin .checkbox-list {
129
+ display: inline-block; }
130
+ .rta-admin .checkbox-list .item {
131
+ display: flex;
132
+ margin: 5px 0px;
133
+ float: left;
134
+ clear: both;
135
+ justify-content: space-between;
136
+ width: 100%; }
137
+ .rta-admin .checkbox-list .item span {
138
  display: inline-block;
139
+ margin-right: 14px; }
140
+ .rta-admin .checkbox-list .item span.hidden {
141
+ visibility: hidden; }
142
+ .rta-admin .checkbox-list input {
143
+ margin-right: 8px; }
144
+ .rta-admin .select-options {
145
+ margin-left: 200px;
146
+ margin-top: 15px; }
147
+ .rta-admin .select-options > span {
148
+ cursor: pointer;
149
+ color: #222;
150
+ margin-right: 12px;
151
+ display: inline-block; }
152
+ .rta-admin .select-options .note {
153
+ margin-left: 0;
154
+ border: 1px solid #ccc;
155
+ padding: 8px; }
156
+ .rta-admin .cleanup-wrapper {
157
+ padding: 8px;
158
+ border: 1px solid #ddd; }
159
+ .rta-admin .cleanup-wrapper .option {
160
+ display: flex;
161
+ flex: 1; }
162
+ .rta-admin .cleanup-wrapper .option .note {
163
+ flex: 2; }
164
+ .rta-admin .warning-removal {
165
+ position: relative;
166
+ text-decoration: line-through; }
167
+ .rta-admin .warning-removal .icon-warning {
168
+ font-size: 30px;
169
+ color: #ff0000;
170
+ width: 20px;
171
+ height: 20px;
172
+ text-decoration: none;
173
  position: absolute;
174
+ left: -30px;
175
+ top: -7px;
176
+ margin: 0; }
177
+ .rta-admin .form_controls {
178
+ position: absolute;
179
+ left: 45px;
180
+ bottom: 0px; }
181
+ .rta-admin .form_controls .save_indicator {
182
+ display: none;
183
+ color: #049901;
184
+ font-weight: 700;
185
+ background: url("/wp-admin/images/wpspin_light.gif") no-repeat left center;
186
+ background-size: 16px 16px;
187
+ padding-left: 20px; }
188
+ .rta-admin .form_controls .save_indicator .saved {
189
+ font-size: 60px; }
190
+ .rta-admin .form_controls .save_note {
191
+ color: orange;
192
+ float: right;
193
+ margin-left: 30px; }
194
+ .rta-admin .toggle-window {
195
+ cursor: pointer; }
196
+ .rta-admin .toggle-window h4 {
197
+ display: inline-block; }
198
+ .rta-admin .toggle-window span {
199
+ font-size: 26px;
200
+ vertical-align: top;
201
+ margin-top: 4px; }
202
+ .rta-admin .window-up, .rta-admin .window-down {
203
+ transition: all 500ms linear; }
204
+ .rta-admin .window-up {
205
+ opacity: 0; }
206
+ .rta-admin .window-down {
207
+ opacity: 100; }
css/rta.css CHANGED
@@ -6,13 +6,10 @@
6
  .rta_ajax_loader{display: none;border: 16px solid #f3f3f3;border-top: 16px solid #0173ab;border-radius: 50%;width: 30px;height: 30px;animation: spin 2s linear infinite;margin:0px auto;}
7
  .rta_ajax_loader_folder{width: 3px;height: 3px;position: absolute;border: 7px solid #ccc;border-top: 7px solid #0173ab;margin-top: -17px;}
8
  @keyframes spin {0% { transform: rotate(0deg); }100% { transform: rotate(360deg); }}
9
- .rta_wait_loader{background: url("../images/ajax-loader.gif") no-repeat left top;padding-left: 20px;display:none; }
10
  .rta_hidden{display: none;}
11
  .rta_text_field_60{width: 100px;}
12
  .rta_error_link{font-size: 16px;font-weight: bold;text-decoration: underline !important;}
13
- .CircularProgressbar {
14
- width: 100%;
15
- }
16
  svg:not(:root) {
17
  overflow: hidden;
18
  }
@@ -23,20 +20,7 @@ img {
23
  display: inline-block;
24
  width: 200px;
25
  }
26
- .CircularProgressbar .CircularProgressbar-trail {
27
- stroke: #d6d6d6;
28
- }
29
- .CircularProgressbar .CircularProgressbar-path {
30
- stroke: #3e98c7;
31
- stroke-linecap: round;
32
- transition: stroke-dashoffset 0.5s ease 0s;
33
- }
34
- .CircularProgressbar .CircularProgressbar-text {
35
- fill: #3e98c7;
36
- font-size: 20px;
37
- dominant-baseline: middle;
38
- text-anchor: middle;
39
- }
40
  #rtaContent .cpbParent .images {
41
  border: 1px solid #cecece;
42
  padding: 0px 15px 15px 15px;
6
  .rta_ajax_loader{display: none;border: 16px solid #f3f3f3;border-top: 16px solid #0173ab;border-radius: 50%;width: 30px;height: 30px;animation: spin 2s linear infinite;margin:0px auto;}
7
  .rta_ajax_loader_folder{width: 3px;height: 3px;position: absolute;border: 7px solid #ccc;border-top: 7px solid #0173ab;margin-top: -17px;}
8
  @keyframes spin {0% { transform: rotate(0deg); }100% { transform: rotate(360deg); }}
 
9
  .rta_hidden{display: none;}
10
  .rta_text_field_60{width: 100px;}
11
  .rta_error_link{font-size: 16px;font-weight: bold;text-decoration: underline !important;}
12
+
 
 
13
  svg:not(:root) {
14
  overflow: hidden;
15
  }
20
  display: inline-block;
21
  width: 200px;
22
  }
23
+
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  #rtaContent .cpbParent .images {
25
  border: 1px solid #cecece;
26
  padding: 0px 15px 15px 15px;
js/rta.js CHANGED
@@ -10,19 +10,19 @@ rtaJS.prototype = {
10
  is_stopped: false,
11
  formcookie: null,
12
  is_saved: true,
13
-
14
  }
15
 
16
  rtaJS.prototype.init = function()
17
  {
 
18
  this.checkSubmitReady();
19
 
20
  $('.select, .deselect').on('click', $.proxy(this.selectAll, this));
21
  $(document).on('change','input, select', $.proxy(this.checkSubmitReady, this));
22
 
23
  // the start of it all.
24
- $(document).on("click", '.rta_regenerate', $.proxy(this.processInit, this));
25
- //$('#frm_rta_image_sizes').on('submit', $.proxy(this.processInit, this))
26
 
27
  // save image sizes when updated
28
  $(document).on('change', '.table.imagesizes input, .table.imagesizes select', $.proxy(this.image_size_changed, this));
@@ -30,28 +30,24 @@ rtaJS.prototype.init = function()
30
  $(document).on('click', '.table.imagesizes .btn_remove_row', $.proxy(this.remove_image_size_row, this));
31
  $(document).on('click', '#btn_add_image_size', $.proxy(this.add_image_size_row, this));
32
  $(document).on('click', '.stop-process', $.proxy(this.stopProcess,this));
 
 
 
33
 
34
- $(document).on('click', '.rta_error_link', $.proxy(function () { this.show_errorbox(true); }, this) ) ;
35
- this.formcookie = this.get_form_cookie();
 
 
 
36
 
37
  $(document).on('change', '.rta-settings-wrap input, .rta-settings-wrap select', $.proxy(this.show_save_indicator, this) );
38
  $(document).on('change', 'input[name^="regenerate_sizes"]', $.proxy(this.checkOptionsVisible, this));
39
 
40
- var offset = parseInt(this.get_cookie('rta_offset'));
41
- var total = parseInt(this.get_cookie('rta_total'));
42
 
43
- if (! isNaN(offset) && ! isNaN(total))
44
- {
45
- if (offset < total)
46
- {
47
- this.is_interrupted_process = true;
48
- this.offset = offset;
49
- this.total = total;
50
- this.process();
51
- }
52
- }
53
  }
54
 
 
55
  rtaJS.prototype.checkSubmitReady = function()
56
  {
57
  processReady = true;
@@ -89,6 +85,24 @@ rtaJS.prototype.checkSubmitReady = function()
89
 
90
  }
91
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  rtaJS.prototype.selectAll = function(e)
93
  {
94
  var action = $(e.target).data('action');
@@ -101,27 +115,31 @@ rtaJS.prototype.selectAll = function(e)
101
  }
102
 
103
  $('input[name^="' + target + '"]').prop('checked', checked).trigger('change');
104
-
105
  }
106
 
107
- rtaJS.prototype.processInit = function (e)
 
108
  {
109
  e.preventDefault();
110
 
111
- this.unset_all_cookies();
112
- this.show_errorbox(false);
113
- this.hide_progress();
114
- this.toggleShortPixelNotice(false);
115
 
116
- this.show_wait(true);
 
 
 
 
117
 
118
  this.in_process = true;
119
  this.is_stopped = false;
120
  this.checkSubmitReady();
121
- this.set_form_cookie();
122
 
123
  var self = this;
124
- var form = this.get_form_cookie();
125
 
126
  $.ajax({
127
  type: 'POST',
@@ -129,27 +147,47 @@ rtaJS.prototype.processInit = function (e)
129
  url: rta_data.ajaxurl,
130
  data: {
131
  gen_nonce: rta_data.nonce_generate,
132
- action: 'rta_regenerate_thumbnails',
133
- type: 'general',
134
- genform: JSON.stringify(form),
135
  },
136
  success: function (response) {
137
- if( response.pCount > 0 ) {
138
- self.offset = 0;
139
- self.total = response.pCount;
140
- self.set_process_cookie(self.offset, self.total);
 
 
141
  self.process();
142
- }else{
143
- self.finishProcess();
144
- self.add_error(response.logstatus);
145
- self.show_errorlink(true);
146
- }
147
  }
148
  });
149
  }
150
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
  rtaJS.prototype.process = function()
152
  {
 
 
153
  if (this.is_stopped)
154
  return; // escape if process has been stopped.
155
  offset = this.offset;
@@ -157,12 +195,13 @@ rtaJS.prototype.process = function()
157
 
158
  this.in_process = true;
159
  this.checkSubmitReady();
 
 
 
160
 
161
- var percentage_done = Math.round((offset/total)*100);
162
- this.show_progress(percentage_done);
163
  var self = this;
164
 
165
- var form = this.get_form_cookie();
166
 
167
  if(offset < total) {
168
  $.ajax({
@@ -174,37 +213,67 @@ rtaJS.prototype.process = function()
174
  action: 'rta_regenerate_thumbnails',
175
  type: 'submit',
176
  offset:offset,
177
- genform: JSON.stringify(form),
178
  },
179
  success: function (response) {
180
- if( response.offset <= total ) {
181
- if(response.logstatus=='Processed') {
182
- $(".rta_progress .images img").attr("src",response.imgUrl);
183
- }
184
 
 
 
 
 
 
 
 
 
 
185
  if (! self.is_stopped)
186
  {
187
- self.set_process_cookie(response.offset,total);
188
- self.offset = response.offset;
189
  setTimeout(function(){ self.process(); },400);
190
  }
191
  }else{
192
- self.set_cookie("rta_image_processed",$(".rta_progress .images img").attr("src"));
193
  //this.show_buttons();
194
- self.show_errorlink(true);
195
- }
196
- if($.isArray(response.error) && response.error.length > 0) {
197
- self.add_error(response.logstatus);
198
  }
199
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200
  });
201
  }else{
202
- this.set_cookie("rta_image_processed",$(".rta_progress .images img").attr("src"));
203
  //this.show_buttons();
204
  this.finishProcess();
205
- this.show_errorlink(true);
206
  }
207
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208
  }
209
 
210
  rtaJS.prototype.finishProcess = function()
@@ -212,195 +281,195 @@ rtaJS.prototype.process = function()
212
  this.in_process = false;
213
  this.is_interrupted_process = false;
214
 
215
- this.show_wait(false);
216
- this.toggleShortPixelNotice(true);
217
- $('.stop-process').addClass('rta_hidden');
 
 
 
 
 
 
 
218
  this.checkSubmitReady();
219
  }
220
 
221
  rtaJS.prototype.stopProcess = function()
222
  {
223
- if (confirm(rta_data.confirm_stop))
224
  {
225
  this.is_stopped = true;
226
- this.unset_all_cookies();
227
- this.finishProcess();
228
- this.hide_progress();
229
- this.toggleShortPixelNotice(false);
230
- // this.checkSubmitReady();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
231
  }
232
  }
233
 
234
- rtaJS.prototype.show_progress = function(percentage_done) {
235
- //var $ = jQuery;
236
- if($(".rta_progress .images img").attr("src").indexOf("http") != -1 ) {
237
- $(".rta_progress .images").css('opacity', 100);
238
- }else{
239
- $(".rta_progress .images").css('opacity', 0);
240
- }
 
 
 
 
 
241
  var total_circle = 289.027;
242
  if(percentage_done>0) {
243
  total_circle = Math.round(total_circle-(total_circle*percentage_done/100));
244
  }
245
  $(".CircularProgressbar-path").css("stroke-dashoffset",total_circle+"px");
246
  $(".CircularProgressbar-text").html(percentage_done+"%");
247
- if(!$(".rta_progress").is(":visible")) {
 
 
 
248
 
249
  this.show_wait(false);
250
  $('.rta_progress').removeClass('rta_hidden');
251
  $('.stop-process').removeClass('rta_hidden');
252
  $(".rta_progress").slideDown();
253
  $(".rta_progress").css('display', 'inline-block');
254
- }
255
  }
256
 
257
- rtaJS.prototype.show_wait = function(show) {
258
- if (! show)
259
- $(".rta_wait_loader").hide();
260
- else
261
- $(".rta_wait_loader").show().removeClass('rta_hidden');
262
- }
263
-
264
- rtaJS.prototype.add_error = function(log) {
265
- // var $ = jQuery;
266
- if(log!="") {
267
- var html = '';
268
- if($.isArray(log)){
269
- for(var i=0;i<=log.length;i++) {
270
- html = html+'<li class="list-group-item headLi">'+log[i]+'</li>';
271
- }
272
- }else{
273
- html = '<li class="list-group-item headLi">'+log+'</li>';
274
- }
275
- $(".rta_error_box ul").append(html);
276
- this.set_cookie("rta_error_box_ul",$(".rta_error_box ul").html());
277
- }
278
- }
 
 
 
279
 
280
- rtaJS.prototype.show_errorbox = function(show) {
281
- // var $ = jQuery;
282
- if (!show)
283
- {
284
- $(".rta_error_box").slideUp(10);
285
- $(".rta_error_box ul").html("");
286
- $(".rta_error_link").slideUp(10);
287
-
288
- }
289
- else {
290
- if(!$(".rta_error_box").is(":visible") && $(".rta_error_box ul li").length) {
291
- $(".rta_error_box").removeClass('rta_hidden').slideDown();
292
- }
293
- }
294
-
295
- return false;
296
- }
297
 
298
- rtaJS.prototype.show_errorlink = function() {
299
- // var $ = jQuery;
300
- if(!$(".rta_error_link").is(":visible") && $(".rta_error_box ul li").length) {
301
- $(".rta_error_link").removeClass('rta_hidden').slideDown();
 
 
 
 
302
  }
303
- }
304
-
305
- rtaJS.prototype.hide_progress = function() {
306
- var $ = jQuery;
307
- var total_circle = 289.027;
308
- $(".rta_progress .images img").attr("src","");
309
- $(".CircularProgressbar-path").css("stroke-dashoffset",total_circle+"px");
310
- $(".rta_progress .images").css('opacity', 0);
311
- $(".rta_progress").slideUp();
312
- $(".CircularProgressbar-text").html("0%");
313
- }
314
 
315
- rtaJS.prototype.unset_all_cookies = function() {
316
- this.set_cookie("rta_image_processed","");
317
- this.set_cookie("rta_offset","");
318
- this.set_cookie("rta_total","");
319
- this.set_cookie('rta_last_settings', '');
 
 
 
320
  }
321
 
322
- /* Empty function, disabling
323
- rtaJS.prototype.set_default_values = function() {
324
- } */
325
-
326
- rtaJS.prototype.set_process_cookie = function(offset, total)
327
  {
328
- offset = parseInt(offset);
329
- total = parseInt(total);
 
 
 
330
 
331
- if (! isNaN(offset))
332
- this.set_cookie('rta_offset', offset);
333
- if (! isNaN(total))
334
- this.set_cookie('rta_total', total);
335
- }
336
 
337
- rtaJS.prototype.get_form_cookie = function()
338
- {
339
- var cook = this.get_cookie('rta_last_settings');
340
- formcookie = {};
341
- if (cook.length > 0)
342
- formcookie = JSON.parse(cook);
343
-
344
- return formcookie;
345
  }
346
 
347
- rtaJS.prototype.set_form_cookie = function() {
348
- var formcookie = {};
349
- $('#frm_rta_image_sizes').find('input, select').each(function()
350
- {
351
- var value = $(this).val();
352
- var name = $(this).attr('name');
353
 
354
- if (name.indexOf('image_sizes[') >= 0)
355
- {
356
- return true;
357
- }
358
 
359
- if ( $(this).attr('type') == 'checkbox' && ! $(this).prop('checked') )
360
- {
361
- return true; // continue if not checked..
362
- }
 
 
 
363
 
364
- // Restore array of inputs with array. Needlessly complicated.
365
- // 1 = name of input without [] , 2 is index of input.
366
- matches = name.match(/(.*?)\[(.*)\]/);
367
- if (matches !== null)
368
- {
369
- if (!formcookie[matches[1]]) {
370
- formcookie[matches[1]] = [];
371
  }
372
- formcookie[matches[1]][matches[2]] = value;
373
- }
374
- else
375
- formcookie[name] = value;
376
- });
377
 
378
- this.set_cookie('rta_last_settings', JSON.stringify(formcookie), 10);
 
 
 
 
 
379
  }
380
 
381
- rtaJS.prototype.set_cookie = function(cname, cvalue, exdays) {
382
- var d = new Date();
383
- d.setTime(d.getTime() + (exdays*24*60*60*1000));
384
- var expires = "expires="+ d.toUTCString();
385
- document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
386
  }
387
 
388
- rtaJS.prototype.get_cookie = function(cname) {
389
 
390
- var name = cname + "=";
391
- var decodedCookie = decodeURIComponent(document.cookie);
392
- var ca = decodedCookie.split(';');
393
- for(var i = 0; i <ca.length; i++) {
394
- var c = ca[i];
395
- while (c.charAt(0) == ' ') {
396
- c = c.substring(1);
397
- }
398
- if (c.indexOf(name) == 0) {
399
- return c.substring(name.length, c.length);
400
- }
401
- }
402
- return "";
403
  }
 
404
 
405
  rtaJS.prototype.add_image_size_row = function() {
406
 
@@ -478,6 +547,7 @@ rtaJS.prototype.process = function()
478
  self.is_saved = true;
479
  self.settings_doingsave_indicator(false);
480
  self.checkSubmitReady();
 
481
  }
482
  });
483
  }
@@ -499,18 +569,10 @@ rtaJS.prototype.process = function()
499
  this.checkSubmitReady();
500
  }
501
 
502
- rtaJS.prototype.toggleShortPixelNotice = function(show)
503
- {
504
- if (show)
505
- $('.shortpixel-bulk-notice, .shortpixel-notice').removeClass('rta_hidden');
506
- else
507
- $('.shortpixel-bulk-notice, .shortpixel-notice').addClass('rta_hidden');
508
- }
509
-
510
  rtaJS.prototype.remove_image_size_row = function(e) {
511
  var rowid = $(e.target).parents('.row').attr('id');
512
 
513
- if(confirm( rta_data.confirm_delete )) {
514
  var intName = $('#' + rowid).find('.image_sizes_name').val();
515
  $('input[name^="regenerate_sizes"][value="' + intName + '"]').remove(); // remove the checkbox as well, otherwise this will remain saved.
516
 
@@ -541,6 +603,55 @@ rtaJS.prototype.process = function()
541
  });
542
  }
543
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
544
  window.rtaJS = new rtaJS();
545
  window.rtaJS.init();
546
 
10
  is_stopped: false,
11
  formcookie: null,
12
  is_saved: true,
 
13
  }
14
 
15
  rtaJS.prototype.init = function()
16
  {
17
+ this.initProcess();
18
  this.checkSubmitReady();
19
 
20
  $('.select, .deselect').on('click', $.proxy(this.selectAll, this));
21
  $(document).on('change','input, select', $.proxy(this.checkSubmitReady, this));
22
 
23
  // the start of it all.
24
+ //$(document).on("click", '.rta_regenerate', $.proxy(this.processInit, this));
25
+ $('#rtaform_process').on('submit', $.proxy(this.startProcess, this));
26
 
27
  // save image sizes when updated
28
  $(document).on('change', '.table.imagesizes input, .table.imagesizes select', $.proxy(this.image_size_changed, this));
30
  $(document).on('click', '.table.imagesizes .btn_remove_row', $.proxy(this.remove_image_size_row, this));
31
  $(document).on('click', '#btn_add_image_size', $.proxy(this.add_image_size_row, this));
32
  $(document).on('click', '.stop-process', $.proxy(this.stopProcess,this));
33
+ $(document).on('click', '.rta_success_box .modal-close', $.proxy(function(e){
34
+ this.togglePanel('success', false);
35
+ }, this));
36
 
37
+ // Warnings, errors and such.
38
+ $(document).on('change', 'input[name="del_associated_thumbs"]', $.proxy(this.toggleDeleteItems,this));
39
+ $(document).on('change', 'input[name^="regenerate_sizes"]', $.proxy(this.toggleDeleteItems,this));
40
+ //this.formcookie = this.get_form_cookie();
41
+ this.toggleDeleteItems();
42
 
43
  $(document).on('change', '.rta-settings-wrap input, .rta-settings-wrap select', $.proxy(this.show_save_indicator, this) );
44
  $(document).on('change', 'input[name^="regenerate_sizes"]', $.proxy(this.checkOptionsVisible, this));
45
 
46
+ $('.toggle-window').on('click', $.proxy(this.toggleWindow, this));
 
47
 
 
 
 
 
 
 
 
 
 
 
48
  }
49
 
50
+ // function to check if admin screen can start a new job.
51
  rtaJS.prototype.checkSubmitReady = function()
52
  {
53
  processReady = true;
85
 
86
  }
87
 
88
+ // Function to check if there was a interrupted process via rta_data.
89
+ rtaJS.prototype.initProcess = function()
90
+ {
91
+ process = rta_data.process;
92
+
93
+ if (process.running)
94
+ this.in_process = process.running;
95
+
96
+ if (process.current)
97
+ this.offset = process.current;
98
+
99
+ if (process.total)
100
+ this.total = process.total;
101
+
102
+ if (this.in_process)
103
+ this.resumeProcess();
104
+ }
105
+
106
  rtaJS.prototype.selectAll = function(e)
107
  {
108
  var action = $(e.target).data('action');
115
  }
116
 
117
  $('input[name^="' + target + '"]').prop('checked', checked).trigger('change');
 
118
  }
119
 
120
+ // starts the process.
121
+ rtaJS.prototype.startProcess = function (e)
122
  {
123
  e.preventDefault();
124
 
125
+ //this.unset_all_cookies();
126
+ this.resetPanels();
127
+ this.togglePanel('main', true);
128
+ this.togglePanel('loading', true);
129
 
130
+ var status = new Object;
131
+ status.id = -1;
132
+ status.message = rta_data.strings.status_start;
133
+ status.error = true;
134
+ this.add_status([status]);
135
 
136
  this.in_process = true;
137
  this.is_stopped = false;
138
  this.checkSubmitReady();
139
+ //this.set_form_cookie();
140
 
141
  var self = this;
142
+ var form = $('#rtaform_process');
143
 
144
  $.ajax({
145
  type: 'POST',
147
  url: rta_data.ajaxurl,
148
  data: {
149
  gen_nonce: rta_data.nonce_generate,
150
+ action: 'rta_start_regenerate',
151
+ // type: 'general',
152
+ genform: form.serialize(),
153
  },
154
  success: function (response) {
155
+ self.offset = response.current;
156
+ self.total = response.total;
157
+ if (response.status)
158
+ {
159
+ self.add_status(response.status);
160
+ }
161
  self.process();
162
+ },
163
+ error: function(response)
164
+ {
165
+ self.finishProcess();
 
166
  }
167
  });
168
  }
169
 
170
+ // function was interrupted, but will continue now; draw panels.
171
+ rtaJS.prototype.resumeProcess = function()
172
+ {
173
+ this.resetPanels();
174
+ this.togglePanel('main', true);
175
+ this.togglePanel('loading', true);
176
+
177
+ var status = new Object;
178
+ status.id = -1;
179
+ status.message = rta_data.strings.status_resume;
180
+ status.error = true;
181
+ this.add_status([status]);
182
+
183
+ this.process();
184
+ }
185
+
186
+ // function for getting the next image in line.
187
  rtaJS.prototype.process = function()
188
  {
189
+ this.togglePanel('loading', false);
190
+
191
  if (this.is_stopped)
192
  return; // escape if process has been stopped.
193
  offset = this.offset;
195
 
196
  this.in_process = true;
197
  this.checkSubmitReady();
198
+ this.updateProgress();
199
+ this.togglePanel('progress', true);
200
+ this.processStoppable();
201
 
 
 
202
  var self = this;
203
 
204
+ //var form = this.get_form_cookie();
205
 
206
  if(offset < total) {
207
  $.ajax({
213
  action: 'rta_regenerate_thumbnails',
214
  type: 'submit',
215
  offset:offset,
216
+ //genform: JSON.stringify(form),
217
  },
218
  success: function (response) {
 
 
 
 
219
 
220
+ if (response.status)
221
+ {
222
+ self.add_status(response.status);
223
+ }
224
+ if( response.current <= total ) {
225
+ /*if(response.logstatus=='Processed') {
226
+ this.togglePanel('thumbnail', true);
227
+ $(".rta_progress .images img").attr("src",response.imgUrl);
228
+ } */
229
  if (! self.is_stopped)
230
  {
231
+ // self.set_process_cookie(response.offset,total);
232
+ self.offset = response.current;
233
  setTimeout(function(){ self.process(); },400);
234
  }
235
  }else{
236
+ // self.set_cookie("rta_image_processed",$(".rta_progress .images img").attr("src"));
237
  //this.show_buttons();
238
+ // self.show_errorlink(true);
 
 
 
239
  }
240
+
241
+ },
242
+ error: function (response) {
243
+
244
+ var status = new Object;
245
+ status.id = -1;
246
+ status.message = response.status + ' ' + response.statusText + ' :: ' + self.offset;
247
+ status.error = true;
248
+ self.add_status([status]);
249
+
250
+ self.offset++;
251
+ if( self.offset <= total ) {
252
+ self.process(); // continue if we still can.
253
+ }
254
+ },
255
  });
256
  }else{
257
+ // this.set_cookie("rta_image_processed",$(".rta_progress .images img").attr("src"));
258
  //this.show_buttons();
259
  this.finishProcess();
 
260
  }
261
 
262
+ }
263
+
264
+ // check if progress is stoppable and activate stop process button, or not.
265
+ rtaJS.prototype.processStoppable = function()
266
+ {
267
+ var stoppable = false;
268
+
269
+ if (this.in_process)
270
+ stoppable = true;
271
+
272
+ if (stoppable)
273
+ $('.stop-process').prop('disabled', false);
274
+ else
275
+ $('.stop-process').prop('disabled', true);
276
+
277
  }
278
 
279
  rtaJS.prototype.finishProcess = function()
281
  this.in_process = false;
282
  this.is_interrupted_process = false;
283
 
284
+ this.togglePanel('success', true);
285
+ this.processStoppable();
286
+ //this.toggleShortPixelNotice(true);
287
+ // $('.stop-process').addClass('rta_hidden');
288
+ var status = new Object;
289
+ status.id = -1;
290
+ status.message = rta_data.strings.status_finish;
291
+ status.error = true;
292
+ this.add_status([status]);
293
+
294
  this.checkSubmitReady();
295
  }
296
 
297
  rtaJS.prototype.stopProcess = function()
298
  {
299
+ if (confirm(rta_data.strings.confirm_stop))
300
  {
301
  this.is_stopped = true;
302
+
303
+ this.togglePanel('loading', true);
304
+ var self = this;
305
+
306
+ $.ajax({
307
+ type: 'POST',
308
+ dataType: 'json',
309
+ url: rta_data.ajaxurl,
310
+ data: {
311
+ gen_nonce: rta_data.nonce_generate,
312
+ action: 'rta_stop_process',
313
+ type: 'submit',
314
+ },
315
+ success: function (response) {
316
+ if (response.status)
317
+ {
318
+ self.add_status(response.status);
319
+ }
320
+ self.finishProcess();
321
+ self.togglePanel('loading', false);
322
+
323
+ }
324
+
325
+ });
326
+
327
  }
328
  }
329
 
330
+ rtaJS.prototype.updateProgress = function(percentage_done) {
331
+
332
+ var offset = parseInt(this.offset);
333
+ var total = parseInt(this.total);
334
+
335
+ if (offset == 0 && total > 0)
336
+ percentage_done = 0;
337
+ else if (total > 0)
338
+ percentage_done = Math.round( (offset/total) * 100);
339
+ else
340
+ percentage_done = 100;
341
+
342
  var total_circle = 289.027;
343
  if(percentage_done>0) {
344
  total_circle = Math.round(total_circle-(total_circle*percentage_done/100));
345
  }
346
  $(".CircularProgressbar-path").css("stroke-dashoffset",total_circle+"px");
347
  $(".CircularProgressbar-text").html(percentage_done+"%");
348
+
349
+ $('.progress-count .current').text(offset);
350
+ $('.progress-count .total').text(total);
351
+ /*f(!$(".rta_progress").is(":visible")) {
352
 
353
  this.show_wait(false);
354
  $('.rta_progress').removeClass('rta_hidden');
355
  $('.stop-process').removeClass('rta_hidden');
356
  $(".rta_progress").slideDown();
357
  $(".rta_progress").css('display', 'inline-block');
358
+ } */
359
  }
360
 
361
+ rtaJS.prototype.togglePanel = function(name, show)
362
+ {
363
+ var panel;
364
+
365
+ switch(name)
366
+ {
367
+ case 'main':
368
+ panel = 'section.regenerate';
369
+ break;
370
+ case 'loading':
371
+ panel = ".rta_wait_loader";
372
+ break;
373
+ case 'progress':
374
+ panel = '.rta_progress_view';
375
+ break;
376
+ case 'thumbnail':
377
+ panel = '.rta_thumbnail_view';
378
+ break;
379
+ case 'success':
380
+ panel = '.rta_success_box';
381
+ break;
382
+ case 'notices':
383
+ panel = '.rta_notices';
384
+ break;
385
+ }
386
 
387
+ var is_visible = $(panel).is(':visible');
388
+ if (is_visible)
389
+ {
390
+ // zero opacity is considered visible by Jquery.
391
+ if ($(panel).css('opacity') == 0)
392
+ is_visible = false;
393
+ }
 
 
 
 
 
 
 
 
 
 
394
 
395
+ if (show && ! is_visible)
396
+ {
397
+ if ($(panel).hasClass('rta_hidden'))
398
+ {
399
+ $(panel).slideDown();
400
+ }
401
+ else {
402
+ $(panel).css('opacity', 1);
403
  }
 
 
 
 
 
 
 
 
 
 
 
404
 
405
+ }
406
+ else if (! show && is_visible)
407
+ {
408
+ if ($(panel).hasClass('rta_hidden'))
409
+ $(panel).hide();
410
+ else
411
+ $(panel).css('opacity', 0);
412
+ }
413
  }
414
 
415
+ rtaJS.prototype.resetPanels = function()
 
 
 
 
416
  {
417
+ this.togglePanel('loading', false);
418
+ this.togglePanel('progress', false);
419
+ this.togglePanel('thumbnail', false);
420
+ this.togglePanel('success', false);
421
+ this.togglePanel('notices', false);
422
 
423
+ $('.rta_notices .statuslist li').remove(); // empty previous statuses
 
 
 
 
424
 
 
 
 
 
 
 
 
 
425
  }
426
 
427
+ rtaJS.prototype.add_status = function(status) {
428
+ // var $ = jQuery;
429
+ this.togglePanel('notices', true);
 
 
 
430
 
431
+ if(status!="") {
432
+ var html = '';
 
 
433
 
434
+ for(var i=0;i < status.length;i++) {
435
+ var item = status[i];
436
+ var item_class = '';
437
+ if (item.error)
438
+ item_class = 'error';
439
+ else
440
+ item_class = '';
441
 
442
+ if(item.status == 1) // status 1 is successfully regenerated thumbnail with URL in message.
443
+ {
444
+ this.showThumb(item.message);
445
+ continue;
 
 
 
446
  }
 
 
 
 
 
447
 
448
+
449
+ html = html+'<li class="list-group-item ' + item_class + '">'+ item.message +'</li>';
450
+ }
451
+ $(".rta_status_box ul.statuslist").append(html);
452
+
453
+ }
454
  }
455
 
456
+ rtaJS.prototype.showThumb = function(imgUrl)
457
+ {
458
+ this.togglePanel('thumbnail', true);
459
+ $(".rta_progress .images img").attr("src",imgUrl);
 
460
  }
461
 
 
462
 
463
+ /* rtaJS.prototype.hide_progress = function() {
464
+ var $ = jQuery;
465
+ var total_circle = 289.027;
466
+ $(".rta_progress .images img").attr("src","");
467
+ $(".CircularProgressbar-path").css("stroke-dashoffset",total_circle+"px");
468
+ $(".rta_progress .images").css('opacity', 0);
469
+ $(".rta_progress").slideUp();
470
+ $(".CircularProgressbar-text").html("0%");
 
 
 
 
 
471
  }
472
+ */
473
 
474
  rtaJS.prototype.add_image_size_row = function() {
475
 
547
  self.is_saved = true;
548
  self.settings_doingsave_indicator(false);
549
  self.checkSubmitReady();
550
+ self.toggleDeleteItems();
551
  }
552
  });
553
  }
569
  this.checkSubmitReady();
570
  }
571
 
 
 
 
 
 
 
 
 
572
  rtaJS.prototype.remove_image_size_row = function(e) {
573
  var rowid = $(e.target).parents('.row').attr('id');
574
 
575
+ if(confirm( rta_data.strings.confirm_delete )) {
576
  var intName = $('#' + rowid).find('.image_sizes_name').val();
577
  $('input[name^="regenerate_sizes"][value="' + intName + '"]').remove(); // remove the checkbox as well, otherwise this will remain saved.
578
 
603
  });
604
  }
605
 
606
+ rtaJS.prototype.toggleDeleteItems = function()
607
+ {
608
+ $('.checkbox-list label').removeClass('warning-removal');
609
+ $('.checkbox-list .icon-warning').remove();
610
+
611
+ // remove elements added by this func.
612
+ var target = $('input[name="del_associated_thumbs"]');
613
+ if ($(target).is(':checked'))
614
+ {
615
+ var has_items = false;
616
+ $('input[name^="regenerate_sizes"]').not(':checked').each(function()
617
+ {
618
+ //$(this).addClass('rta_hidden');
619
+ $(this).parent('label').addClass('warning-removal');
620
+ $(this).parent('label').find('input').before("<span class='dashicons dashicons-no icon-warning'></span>");
621
+ has_items = true;
622
+ });
623
+
624
+ if (has_items)
625
+ {
626
+ $('#warn-delete-items').removeClass('rta_hidden');
627
+ }
628
+ }
629
+ else {
630
+ $('#warn-delete-items').addClass('rta_hidden');
631
+ }
632
+ //
633
+
634
+ }
635
+
636
+ rtaJS.prototype.toggleWindow = function(e)
637
+ {
638
+ var $target = $(e.target);
639
+ if (! $target.hasClass('toggle-window'))
640
+ $target = $(e.target).parents('.toggle-window');
641
+
642
+ var $window = $('#' + $target.data('window'));
643
+ if ($window.hasClass('window-up'))
644
+ {
645
+ $window.removeClass('window-up').addClass('window-down');
646
+ $target.find('span.dashicons').removeClass('dashicons-arrow-down').addClass('dashicons-arrow-up');
647
+
648
+ }
649
+ else {
650
+ $window.removeClass('window-down').addClass('window-up');
651
+ $target.find('span.dashicons').addClass('dashicons-arrow-down').removeClass('dashicons-arrow-up');
652
+ }
653
+ }
654
+
655
  window.rtaJS = new rtaJS();
656
  window.rtaJS.init();
657
 
readme.txt CHANGED
@@ -3,8 +3,9 @@ Contributors: ShortPixel
3
  Donate link: https://www.paypal.me/resizeImage
4
  Tags: regenerate, thumbnail, thumbnails, thumb, thumbs, easy, media, force regenerate, image, images, pics, date
5
  Requires at least: 4.0
6
- Tested up to: 5.2
7
- Stable tag: 2.1.0
 
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -54,6 +55,18 @@ The script stops but it will resume after you open the settings page of the plug
54
 
55
  == Changelog ==
56
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  = 2.1.0 =
58
 
59
  Release date: 7th June 2019
3
  Donate link: https://www.paypal.me/resizeImage
4
  Tags: regenerate, thumbnail, thumbnails, thumb, thumbs, easy, media, force regenerate, image, images, pics, date
5
  Requires at least: 4.0
6
+ Tested up to: 5.3.2
7
+ Requires PHP: 5.3
8
+ Stable tag: 2.2.0
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
55
 
56
  == Changelog ==
57
 
58
+ = 2.2.0 =
59
+
60
+ Release date: 9th March 2020
61
+ * Reworked and improved the process interface
62
+ * Option in media library to regenerate just one image
63
+ * Will check for post_mime_type in posts and fix it when it's empty.
64
+ * Cookie-based processing removed, now keeps progress as a server setting
65
+ * Internal processes optimized.
66
+ * Fixed - WordPress 5.3 image handling and scaled images
67
+ * Fixed - Metadata not being removed in some cases when "Delete Leftover Image Metadata" is checked.
68
+ * Fixed - Logger doesn't call wp_upload_dir when not debugging
69
+
70
  = 2.1.0 =
71
 
72
  Release date: 7th June 2019
regenerate-thumbnails-advanced.php CHANGED
@@ -1,8 +1,9 @@
1
  <?php
 
2
  /*
3
  Plugin Name: Regenerate Thumbnails Advanced
4
  Description: Regenerate thumbnails fast and easy while removing unused thumbnails of existing images; very useful when changing a theme.
5
- Version: 2.1.0
6
  Author: ShortPixel
7
  Author URI: https://shortpixel.com/
8
  License: GPLv2 or later
@@ -16,23 +17,25 @@ if ( !function_exists( 'add_action' ) ) {
16
  exit;
17
  }
18
 
19
- define( 'RTA_PLUGIN_VERSION', '2.1.0');
20
  define( 'RTA_PLUGIN_PATH', plugin_dir_path(__FILE__) );
21
  define( 'RTA_PLUGIN_URL', plugin_dir_url(__FILE__) );
22
  define( 'RTA_SITE_BASE_URL', rtrim(get_bloginfo('url'),"/")."/");
23
  define( 'RTA_PLUGIN_FILE', __FILE__);
24
  define( 'RTA_LANG_DIR', dirname( plugin_basename(__FILE__) ).'/languages' );
25
 
26
- require_once(RTA_PLUGIN_PATH . 'includes/rta_class.php');
27
- require_once(RTA_PLUGIN_PATH .'rta_admin.php');
 
 
 
 
28
  require_once(RTA_PLUGIN_PATH .'rta_front.php');
29
  require_once(RTA_PLUGIN_PATH . 'classes/rta_admin_controller.php');
30
- require_once(RTA_PLUGIN_PATH . 'classes/rta_image.php');
31
-
32
- $rta = new RTA(); // start runtime
33
 
34
- // define ('RTA_DEBUG', true);
35
 
36
 
37
- register_activation_hook( __FILE__, array( 'RTA', 'rta_install' ) );
38
- register_deactivation_hook( __FILE__, array( 'RTA', 'rta_uninstall' ) );
1
  <?php
2
+ namespace ReThumbAdvanced;
3
  /*
4
  Plugin Name: Regenerate Thumbnails Advanced
5
  Description: Regenerate thumbnails fast and easy while removing unused thumbnails of existing images; very useful when changing a theme.
6
+ Version: 2.2.0
7
  Author: ShortPixel
8
  Author URI: https://shortpixel.com/
9
  License: GPLv2 or later
17
  exit;
18
  }
19
 
20
+ define( 'RTA_PLUGIN_VERSION', '2.2.0');
21
  define( 'RTA_PLUGIN_PATH', plugin_dir_path(__FILE__) );
22
  define( 'RTA_PLUGIN_URL', plugin_dir_url(__FILE__) );
23
  define( 'RTA_SITE_BASE_URL', rtrim(get_bloginfo('url'),"/")."/");
24
  define( 'RTA_PLUGIN_FILE', __FILE__);
25
  define( 'RTA_LANG_DIR', dirname( plugin_basename(__FILE__) ).'/languages' );
26
 
27
+ // define ('RTA_DEBUG', true); // for wp-config
28
+
29
+ require_once(RTA_PLUGIN_PATH . 'build/shortpixel/autoload.php');
30
+ require_once(RTA_PLUGIN_PATH . 'classes/rta_controller.php');
31
+ require_once(RTA_PLUGIN_PATH . 'classes/rta-plugin.php');
32
+ /*require_once(RTA_PLUGIN_PATH .'rta_admin.php');
33
  require_once(RTA_PLUGIN_PATH .'rta_front.php');
34
  require_once(RTA_PLUGIN_PATH . 'classes/rta_admin_controller.php');
35
+ require_once(RTA_PLUGIN_PATH . 'classes/rta_image.php'); */
 
 
36
 
37
+ $rta = new rtaPlugin(); // start runtime
38
 
39
 
40
+ //register_activation_hook( __FILE__, array( 'RTA', 'rta_install' ) );
41
+ //register_deactivation_hook( __FILE__, array( 'RTA', 'rta_uninstall' ) );
scss/rta-admin-progress.scss ADDED
@@ -0,0 +1,208 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ section.regenerate
3
+ {
4
+ background-color: #fff;
5
+ margin-bottom: 200px; // space to WP footer.
6
+
7
+
8
+ .rta_panel_off
9
+ {
10
+ opacity: 0;
11
+ transition: all 0ms linear;
12
+ }
13
+
14
+ .rta_progress {
15
+
16
+ position: relative;
17
+ min-height: 310px;
18
+ width: 65%;
19
+ justify-content: flex-start;
20
+ .rta_progress_view
21
+ {
22
+ margin: 0 auto;
23
+
24
+ svg.CircularProgressbar
25
+ {
26
+ display: inline-block;
27
+ width: 200px;
28
+ padding: 25px 0;
29
+ .CircularProgressbar-trail {
30
+ stroke: #d6d6d6;
31
+ }
32
+ .CircularProgressbar-path {
33
+ stroke: #00bcd4;
34
+ stroke-linecap: round;
35
+ transition: stroke-dashoffset 0.5s ease 0s;
36
+ }
37
+ .CircularProgressbar-text {
38
+ fill: #00bcd4;
39
+ font-size: 20px;
40
+ dominant-baseline: middle;
41
+ text-anchor: middle;
42
+ }
43
+ .progress-count {
44
+ font-size: 9px;
45
+ font-weight: bold;
46
+ dominant-baseline: middle;
47
+ text-anchor: middle;
48
+ fill: 999;
49
+ }
50
+ }
51
+ }
52
+
53
+ .images {
54
+ // margin-left: 225px;
55
+ // float: left;
56
+ padding: 15px;
57
+ border-top: 1px solid #cecece;
58
+ border-bottom: 1px solid #cecece;
59
+
60
+ // margin-right: 50px;
61
+ // opacity: 0;
62
+ width: 60%;
63
+ h5 {
64
+ text-align: center;
65
+ }
66
+ .thumbnail
67
+ {
68
+ text-align: center;
69
+ margin-top: 35px;
70
+ img {
71
+ max-width: 500px;
72
+ max-height: 500px;
73
+ }
74
+ }
75
+
76
+ }
77
+
78
+ } // rta-progress (left)
79
+
80
+
81
+ .rta_status_box
82
+ {
83
+ width: 35%;
84
+ border-left: 1px solid #ccc;
85
+
86
+ .rta_wait_loader
87
+ {
88
+ margin-top: 35px;
89
+ padding-left: 20px;
90
+ opacity: 0;
91
+ //display:none;
92
+ .dashicons {
93
+ animation: wait-spin 2000ms infinite linear;
94
+ width: 35px;
95
+ height: 35px;
96
+ font-size: 35px;
97
+ float: left;
98
+ margin-right: 30px;
99
+
100
+ }
101
+ }
102
+ .rta_notices
103
+ {
104
+
105
+ ul.statuslist {
106
+ max-height: 350px;
107
+ overflow-y: auto;
108
+ overflow-x: visible;
109
+ margin-left: 15px;
110
+ li {
111
+ font-size: 14px;
112
+ &.error
113
+ {
114
+ color: #ff0000;
115
+ }
116
+ }
117
+ }
118
+ }
119
+ h4 {
120
+ font-size: 22px;
121
+ font-weight: bold;
122
+ }
123
+ @keyframes wait-spin {
124
+ 0% {
125
+ transform: rotate(0); }
126
+
127
+ 100% {
128
+ transform: rotate(360deg); }
129
+ }
130
+ }
131
+
132
+ .rta_success_box
133
+ {
134
+ position: absolute;
135
+ left: 30%;
136
+ top: -5%;
137
+ // height: 350px;
138
+ width: 45%;
139
+ margin-left: -200px;
140
+ opacity: 0.9;
141
+ background-color: #fff;
142
+ text-align: center;
143
+ padding: 15px;
144
+ border: 1px solid #00bcd4;
145
+ border-radius: 8px;
146
+
147
+ p {
148
+ font-size: 16px;
149
+ }
150
+
151
+ h3.header {
152
+ font-size: 32px;
153
+ font-weight: bold;
154
+ color: green;
155
+ }
156
+
157
+ .shortpixel
158
+ {
159
+ h3 a {
160
+ line-height: 28px;
161
+ }
162
+ }
163
+
164
+ .modal-close
165
+ {
166
+ position: absolute;
167
+ right: 15px;
168
+ top: 15px;
169
+ cursor: pointer;
170
+ .dashicons
171
+ {
172
+ font-size: 36px;
173
+ width: 36px;
174
+ height: 36px;
175
+ }
176
+
177
+ }
178
+
179
+ } // success_box
180
+
181
+
182
+ .shortpixel-notice
183
+ {
184
+ background: #fff;
185
+ width: 250px;
186
+ min-height: 270px;
187
+ border: 1px solid #ccc;
188
+ padding: 15px;
189
+ margin: 0 5% 10px 25px;
190
+ float: right;
191
+ h3 {
192
+ line-height: 1.3em; // match size
193
+ }
194
+
195
+ }
196
+
197
+
198
+ button.stop-process
199
+ {
200
+ position: absolute;
201
+ bottom: 10px;
202
+ right: 15px;
203
+ font-weight: normal;
204
+ text-transform: none;
205
+ }
206
+
207
+
208
+ } // section.regenerate
scss/rta-admin-view.scss CHANGED
@@ -9,14 +9,12 @@
9
  @include breakpoint(0,1600px)
10
  {
11
  flex-direction: column-reverse;
12
- .rta-regenerate-wrap, .rta-settings-wrap
13
  {
14
  width: 95%;
15
  max-width: none;
16
  }
17
-
18
  }
19
-
20
  }
21
 
22
  h2 {
@@ -28,12 +26,51 @@
28
  margin: 8px 0 8px 15px;
29
  }
30
 
 
31
  form
32
  {
33
  min-height: 600px;
34
  // background: #fff;
35
  padding-bottom: 65px;
 
36
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  }
38
 
39
  .rta-regenerate-wrap, .rta-settings-wrap
@@ -87,15 +124,35 @@
87
  width: 150px;
88
  display: inline-block;
89
  margin-right: 15px;
 
90
  padding: 0 15px;
91
  font-weight: bold;
92
  vertical-align: top;
93
  line-height: 15px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  }
95
  .note
96
  {
97
- font-size: 12px;
98
  margin-left: 15px;
 
 
 
 
99
  }
100
  }
101
 
@@ -190,8 +247,6 @@
190
 
191
  }
192
 
193
-
194
-
195
  }
196
 
197
  .select-options {
@@ -213,70 +268,29 @@
213
  }
214
  }
215
 
216
- section.regenerate
217
  {
218
- background-color: #fff;
219
- .CircularProgressbar
220
- {
221
- display: inline-block;
222
- width: 200px;
223
- padding: 25px 0;
224
- }
225
- .rta_progress {
226
- display: inline-block;
227
- position: relative;
228
- min-height: 310px;
229
- }
230
- .images {
231
- margin-left: 225px;
232
- float: left;
233
- padding: 15px;
234
- border: 1px solid #cecece;
235
- margin-right: 50px;
236
- opacity: 0;
237
- h5 {
238
- text-align: center;
239
- }
240
- img {
241
- max-width: 500px;
242
- max-height: 500px;
243
- }
244
 
245
- }
246
- .rta_hidden
247
- {
248
- display: inline-block;
249
- display: none;
250
- }
251
- .shortpixel-notice
252
- {
253
- background: #fff;
254
- width: 250px;
255
- min-height: 270px;
256
- border: 1px solid #ccc;
257
- padding: 15px;
258
- margin: 0 5% 10px 25px;
259
- float: right;
260
- h3 {
261
- line-height: 1.3em; // match size
262
- }
263
 
264
- }
265
- .shortpixel-bulk-notice
266
- {
267
- font-size: 14px;
268
- font-weight: 700;
269
- text-align: center;
270
- }
271
- button.stop-process
272
  {
 
 
 
 
 
273
  position: absolute;
274
- bottom: 10px;
275
- left: 80%;
276
- font-weight: normal;
277
- text-transform: none;
278
  }
279
- } // section.regenerate
 
 
 
 
280
 
281
  .form_controls
282
  {
@@ -304,9 +318,32 @@
304
  }
305
  }
306
 
307
- // low in the tree, to override most.
308
- /*.rta_hidden
309
  {
310
- display: none !important;
311
- } */
312
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  @include breakpoint(0,1600px)
10
  {
11
  flex-direction: column-reverse;
12
+ .rta-settings-wrap
13
  {
14
  width: 95%;
15
  max-width: none;
16
  }
 
17
  }
 
18
  }
19
 
20
  h2 {
26
  margin: 8px 0 8px 15px;
27
  }
28
 
29
+
30
  form
31
  {
32
  min-height: 600px;
33
  // background: #fff;
34
  padding-bottom: 65px;
35
+ }
36
 
37
+ .rta-notice
38
+ {
39
+ margin: 8px 0;
40
+ padding: 8px;
41
+
42
+ border-width: 1px;
43
+ border-style: solid;
44
+ transition: all 500ms ease-in;
45
+ .icon
46
+ {
47
+ font-size: 35px;
48
+ float: left;
49
+ display: inline-block;
50
+ width: auto;
51
+ height: auto;
52
+
53
+ }
54
+ p {
55
+ font-size: 15px;
56
+ margin: 4px 0;
57
+ margin-left: 45px;
58
+ &.small
59
+ {
60
+ font-size: 0.8em;
61
+ }
62
+ }
63
+ &.warning
64
+ {
65
+ border-color: #ffb900;
66
+ .icon {
67
+ color: #ffb900;
68
+ }
69
+ }
70
+ &.error
71
+ {
72
+ border-color: #ff0000;
73
+ }
74
  }
75
 
76
  .rta-regenerate-wrap, .rta-settings-wrap
124
  width: 150px;
125
  display: inline-block;
126
  margin-right: 15px;
127
+ // margin-left: 15px;
128
  padding: 0 15px;
129
  font-weight: bold;
130
  vertical-align: top;
131
  line-height: 15px;
132
+ position:relative;
133
+ input
134
+ {
135
+ vertical-align: middle;
136
+ display: inline-block;
137
+ // line-height: 35px;
138
+ position: absolute;
139
+ margin-top: 2px;
140
+ // margin-right: 25px;
141
+ }
142
+ span
143
+ {
144
+ display: inline-block;
145
+ margin-left: 25px;
146
+ }
147
  }
148
  .note
149
  {
150
+ //font-size: 12px;
151
  margin-left: 15px;
152
+ p
153
+ {
154
+ margin-top: 0;
155
+ }
156
  }
157
  }
158
 
247
 
248
  }
249
 
 
 
250
  }
251
 
252
  .select-options {
268
  }
269
  }
270
 
271
+ .warning-removal
272
  {
273
+ position: relative;
274
+ text-decoration: line-through;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
275
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
276
 
277
+ .icon-warning
 
 
 
 
 
 
 
278
  {
279
+ font-size: 30px;
280
+ color: #ff0000;
281
+ width: 20px;
282
+ height: 20px;
283
+ text-decoration: none;
284
  position: absolute;
285
+ left: -30px;
286
+ top: -7px;
287
+ margin: 0;
 
288
  }
289
+
290
+ input {
291
+ // display: none;
292
+ }
293
+ }
294
 
295
  .form_controls
296
  {
318
  }
319
  }
320
 
321
+ .toggle-window
 
322
  {
323
+ cursor: pointer;
324
+ h4 {
325
+ display: inline-block;
326
+ }
327
+ span
328
+ {
329
+ font-size: 26px;
330
+ vertical-align: top;
331
+ margin-top: 4px;
332
+ // float: left;
333
+ }
334
+ }
335
+ .window-up, .window-down
336
+ {
337
+ transition: all 500ms linear;
338
+ }
339
+ .window-up
340
+ {
341
+ opacity: 0;
342
+ }
343
+ .window-down
344
+ {
345
+ opacity: 100;
346
+ }
347
+
348
+
349
+ } // class rta-admin
templates/admin/rta_generate_thumbnails.php CHANGED
@@ -1,7 +1,11 @@
1
- <div class="rta-admin-wrap rta-admin">
 
 
 
 
2
  <div class='two-panel-wrap'>
3
  <div class='rta-regenerate-wrap'>
4
- <h2><?php _e('Regenerate Thumbnails','regenerate-thumbnails-advanced'); ?></h2>
5
  <?php $view->loadChildTemplate('view_rta_regenerate'); ?>
6
  </div>
7
  <div class='rta-settings-wrap'>
@@ -12,3 +16,5 @@
12
 
13
  <?php $view->loadChildTemplate('view_regenerate_process'); ?>
14
  </div> <!-- rta admin wrap. -->
 
 
1
+ <div class='wrap'> <!-- this wrap to keep notices and other scum out of the interface -->
2
+ <h1><?php _e('Regenerate Thumbnails Advanced','regenerate-thumbnails-advanced'); ?></h1>
3
+
4
+ <div class="rta-admin-wrap rta-admin wrap">
5
+
6
  <div class='two-panel-wrap'>
7
  <div class='rta-regenerate-wrap'>
8
+ <h2><?php _e('Regenerate Options', 'regenerate-thumbnails-advanced') ?></h2>
9
  <?php $view->loadChildTemplate('view_rta_regenerate'); ?>
10
  </div>
11
  <div class='rta-settings-wrap'>
16
 
17
  <?php $view->loadChildTemplate('view_regenerate_process'); ?>
18
  </div> <!-- rta admin wrap. -->
19
+
20
+ </div>
templates/admin/view_regenerate_process.php CHANGED
@@ -1,44 +1,52 @@
1
 
2
- <section class='regenerate'>
3
- <div class='container'>
4
- <div class="rta_wait_loader"><?php _e('Please wait...','regenerate-thumbnails-advanced'); ?></div>
5
-
6
- <div class="cpbParent rta_progress rta_hidden">
7
- <svg class="CircularProgressbar " viewBox="0 0 100 100">
8
- <path class="CircularProgressbar-trail" d="
9
- M 50,50
10
- m 0,-46
11
- a 46,46 0 1 1 0,92
12
- a 46,46 0 1 1 0,-92
13
- " stroke-width="8" fill-opacity="0">
14
- </path>
15
- <path class="CircularProgressbar-path" d="
16
- M 50,50
17
- m 0,-46
18
- a 46,46 0 1 1 0,92
19
- a 46,46 0 1 1 0,-92
20
- " stroke-width="8" fill-opacity="0" style="stroke-dasharray: 289.027px, 289.027px; stroke-dashoffset: 289.027px;">
21
- </path>
22
- <text class="CircularProgressbar-text" x="50" y="50">0%</text>
23
- </svg>
24
- <div class="images">
25
- <h5><?php _e('Regenerated image:','regenerate-thumbnails-advanced'); ?></h5>
26
- <img src="" alt="">
27
- </div>
28
-
29
- <button class='button stop-process rta_hidden'><?php _e('Stop Process', 'regenerate-thumbnails-advanced') ?></button>
30
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  </div>
32
 
33
- <a href="javascript:void(0);" class="rta_error_link rta_hidden"><?php _e('There were some errors, click for details', 'regenerate-thumbnails-advanced'); ?></a>
34
- <div class="listContainer rta_error_box row rta_hidden">
35
- <div class="statuslist col-sm-6">
36
- <h4 class="listTitle"><?php _e('Error(s)','regenerate-thumbnails-advanced'); ?></h4>
37
- <ul class="list-group">
38
  </ul>
39
  </div>
 
 
 
 
 
 
 
 
40
  </div>
41
 
 
 
42
  <?php
43
  #wp_nonce_field('enable-media-replace');
44
  $plugins = get_plugins();
@@ -47,41 +55,43 @@
47
 
48
  ?>
49
 
50
- <?php if(!$spInstalled): ?>
51
- <div class='shortpixel-notice rta_hidden'>
52
- <h3 class="" style="margin-top: 0;text-align: center;">
53
- <a href="https://shortpixel.com/otp/af/TFXUHHC28044" target="_blank">
54
- <?php echo esc_html__("Optimize your images with ShortPixel, get +50% credits!", "enable-media-replace"); ?>
55
- </a>
56
- </h3>
57
- <div class="" style="text-align: center;">
58
- <a href="https://shortpixel.com/otp/af/TFXUHHC28044" target="_blank">
59
- <img src="https://optimizingmattersblog.files.wordpress.com/2016/10/shortpixel.png">
60
- </a>
61
- </div>
62
- <div class="" style="margin-bottom: 10px;">
63
- <?php echo esc_html__("Get more Google love by compressing your site's images! Check out how much ShortPixel can save your site and get +50% credits when signing up as an Enable Media Replace user! Forever!", "enable-media-replace"); ?>
64
- </div>
65
- <div class=""><div style="text-align: <?php echo (is_rtl()) ? 'left' : 'right' ?>;">
66
- <a class="button button-primary" id="shortpixel-image-optimiser-info" href="https://shortpixel.com/otp/af/TFXUHHC28044" target="_blank">
67
- <?php echo esc_html__("More info", "enable-media-replace"); ?></p>
68
- </a>
69
- </div>
70
- </div>
71
- </div>
72
- <?php
73
- else:
74
- ?>
75
- <div class='shortpixel-bulk-notice rta_hidden'>
76
- <?php if ($spActive): ?>
77
- <p class='gotobulk'><?php printf(__('Thumbnails successfully regenerated. Go to %s ShortPixel Bulk page %s to optimize the updated thumbnails.'), '<a href="' . admin_url('upload.php?page=wp-short-pixel-bulk') . '">', '</a>'); ?></p>
78
- <?php else:
79
- $path = 'shortpixel-image-optimiser/wp-shortpixel.php';
80
- $activate_url = wp_nonce_url(admin_url('plugins.php?action=activate&plugin='.$path), 'activate-plugin_'.$path);
81
- ?>
82
- <p class='gotobulk'><?php printf(__('%s Activate ShortPixel %s to optimize your newly generated thumbnails.'), '<a href="' . $activate_url . '">', '</a>'); ?></p>
83
- <?php endif; ?>
84
- </div>
85
- <?php endif ?>
 
 
86
  </div> <!-- container -->
87
  </section>
1
 
2
+ <section class='regenerate rta_hidden'>
3
+ <div class='container two-panel-wrap'>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
+ <div class="rta_progress two-panel-wrap">
6
+ <div class="images rta_thumbnail_view rta_panel_off">
7
+ <h5><?php _e('Regenerated image:','regenerate-thumbnails-advanced'); ?></h5>
8
+ <div class='thumbnail'> <img src="" alt=""> </div>
9
+ </div>
10
+ <div class='rta_progress_view rta_panel_off'>
11
+ <svg class="CircularProgressbar" viewBox="0 0 100 100">
12
+ <path class="CircularProgressbar-trail" d="
13
+ M 50,50
14
+ m 0,-46
15
+ a 46,46 0 1 1 0,92
16
+ a 46,46 0 1 1 0,-92
17
+ " stroke-width="8" fill-opacity="0">
18
+ </path>
19
+ <path class="CircularProgressbar-path" d="
20
+ M 50,50
21
+ m 0,-46
22
+ a 46,46 0 1 1 0,92
23
+ a 46,46 0 1 1 0,-92
24
+ " stroke-width="8" fill-opacity="0" style="stroke-dasharray: 289.027px, 289.027px; stroke-dashoffset: 289.027px;">
25
+ </path>
26
+ <text class="CircularProgressbar-text" x="50" y="50">0%</text>
27
+ <text class="progress-count" x="50" y="70"><tspan class='current'>0</tspan> / <tspan class='total'>0</tspan></text>
28
+ </svg>
29
+ <button class='button stop-process' disabled><?php _e('Stop Process', 'regenerate-thumbnails-advanced') ?></button>
30
+ </div>
31
  </div>
32
 
33
+ <div class="rta_status_box">
34
+ <div class="rta_notices rta_panel_off">
35
+ <ul class="statuslist">
 
 
36
  </ul>
37
  </div>
38
+ <div class="rta_wait_loader rta_panel_off" >
39
+ <span class='dashicons dashicons-update'>&nbsp;</span>
40
+ <div>
41
+ <h4><?php _e('Starting Process', 'regenerate-thumbnails-advanced'); ?></h4>
42
+ <?php _e('Please wait...','regenerate-thumbnails-advanced'); ?>
43
+ </div>
44
+ </div>
45
+
46
  </div>
47
 
48
+
49
+
50
  <?php
51
  #wp_nonce_field('enable-media-replace');
52
  $plugins = get_plugins();
55
 
56
  ?>
57
 
58
+ <div class='rta_success_box rta_hidden'>
59
+ <div class='modal-close'><span class='dashicons dashicons-no'>&nbsp;</span></div>
60
+ <h3 class='header'><?php _e('Done!', 'regenerate-thumbnails-advanced'); ?></h3>
61
+ <p><?php _e('Regenerate Thumbnails Advanced is done with your task', 'regenerate-thumbnails-advanced'); ?></p>
62
+
63
+ <div class='shortpixel'>
64
+ <?php if (! $spInstalled): ?>
65
+ <h3 class="">
66
+ <a href="https://shortpixel.com/otp/af/TFXUHHC28044" target="_blank">
67
+ <?php echo esc_html__("Optimize your images with ShortPixel, get +50% credits!", "enable-media-replace"); ?>
68
+ </a>
69
+ </h3>
70
+ <div class="">
71
+ <a href="https://shortpixel.com/otp/af/TFXUHHC28044" target="_blank">
72
+ <img src="https://optimizingmattersblog.files.wordpress.com/2016/10/shortpixel.png">
73
+ </a>
74
+ </div>
75
+ <p>
76
+ <?php echo esc_html__("Get more Google love by compressing your site's images! Check out how much ShortPixel can save your site and get +50% credits when signing up as an Enable Media Replace user! Forever!", "enable-media-replace"); ?>
77
+ </p>
78
+ <div class=""><div>
79
+ <a class="button button-primary" id="shortpixel-image-optimiser-info" href="https://shortpixel.com/otp/af/TFXUHHC28044" target="_blank">
80
+ <?php echo esc_html__("More info", "enable-media-replace"); ?></p>
81
+ </a>
82
+ </div>
83
+ </div>
84
+ <?php endif; ?>
85
+ <?php if ($spInstalled && $spActive): ?>
86
+ <p class='gotobulk'><?php printf(__('Thumbnails successfully regenerated. <strong>Go to %s ShortPixel Bulk page %s to optimize the updated thumbnails.</strong>'), '<a href="' . admin_url('upload.php?page=wp-short-pixel-bulk') . '">', '</a>'); ?></p>
87
+ <?php elseif($spInstalled):
88
+ $path = 'shortpixel-image-optimiser/wp-shortpixel.php';
89
+ $activate_url = wp_nonce_url(admin_url('plugins.php?action=activate&plugin='.$path), 'activate-plugin_'.$path);
90
+ ?>
91
+ <p class='gotobulk'><strong><?php printf(__('%s Activate ShortPixel %s to optimize your newly generated thumbnails.'), '<a href="' . $activate_url . '">', '</a>'); ?></strong></p>
92
+ <?php endif; ?>
93
+ </div>
94
+ </div>
95
+
96
  </div> <!-- container -->
97
  </section>
templates/admin/view_rta_regenerate.php CHANGED
@@ -1,6 +1,6 @@
1
 
2
 
3
- <form method="post" name="frm_rta_image_sizes" id="frm_rta_image_sizes" class="frm_rta" enctype="multipart/form-data">
4
  <section class='period'>
5
  <div class='container'>
6
  <div class='option'>
@@ -20,29 +20,63 @@
20
  <input type='checkbox' id='regenonly_featured' name="regenonly_featured" value="1">
21
  </div>
22
  </div>
 
 
23
  </section>
24
 
25
  <section class='extra_options'>
26
  <div class='container'>
27
- <div class='cleanup-wrapper'>
28
- <h4><?php _e('Clean-up options', 'regenerate-thumbnails-advanced') ?></h4>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  <div class='option'>
30
- <label for="del_associated_thumbs"><?php _e('Delete Unused Thumbnails','regenerate-thumbnails-advanced'); ?></label>
31
- <span><input type="checkbox" name="del_associated_thumbs" id="del_associated_thumbs" value="1" /> </span>
32
- <span class='note'><?php _e('This option will remove thumbnails not selected in the settings. Good for stale thumbnails, but be sure they are not in use. ','regenerate-thumbnails-advanced'); ?></span>
 
 
 
 
 
 
 
 
33
  </div>
 
34
  <div class='option'>
35
- <label for="del_leftover_metadata"><?php _e('Delete Leftover Image Metadata','regenerate-thumbnails-advanced'); ?></label>
36
- <span><input type="checkbox" name="del_leftover_metadata" id="del_leftover_metadata" value="1" /> </span>
37
- <span class='note'><?php _e('Delete all the metadata associated with missing (non-existing) images. Keep in mind there is no undo!','regenerate-thumbnails-advanced'); ?></span>
 
 
 
 
 
38
  </div>
 
39
  </div>
40
- </div>
41
  </section>
42
 
43
  <section class='form_controls'>
44
  <div class='container'>
45
- <button type='submit' disabled class='rta_regenerate disabled'><?php _e('Regenerate', 'regenerate-thumbnails-advanced'); ?></button>
46
  <p class='save_note rta_hidden'><?php _e('Save your settings first','regenerate-thumbnails-advanced'); ?></p>
47
  </div>
48
  </section>
1
 
2
 
3
+ <form method="post" name="rtaform_process" id="rtaform_process" class="frm_rta" enctype="multipart/form-data">
4
  <section class='period'>
5
  <div class='container'>
6
  <div class='option'>
20
  <input type='checkbox' id='regenonly_featured' name="regenonly_featured" value="1">
21
  </div>
22
  </div>
23
+
24
+ <input type='hidden' name='posts_per_page' value='3' />
25
  </section>
26
 
27
  <section class='extra_options'>
28
  <div class='container'>
29
+ <div class='toggle-window' data-window='advanced-window'>
30
+ <h4><?php _e('Advanced options', 'regenerate-thumbnails-advanced') ?></h4>
31
+ <span class='dashicons dashicons-arrow-down'>&nbsp;</span>
32
+ </div>
33
+ <div class='cleanup-wrapper window-up' id='advanced-window'>
34
+ <div class='option'>
35
+
36
+ </div>
37
+
38
+ <div class='option'>
39
+ <label>
40
+ <input type='checkbox' name='process_clean_metadata' value='1'>
41
+ <span><?php _e('Clean unknown metadata', 'regenerate-thumbnails-advanced'); ?></span>
42
+ </label>
43
+
44
+ <div class='note'><p><?php _e('Clean old metadata not defined in system sizes. Use after removing plugins / themes with old definitions. Will not remove thumbnails from disk', 'regenerate-thumbnails-advanced') ?></p></div>
45
+ </div>
46
+
47
+
48
  <div class='option'>
49
+ <label for="del_associated_thumbs">
50
+ <input type="checkbox" name="del_associated_thumbs" id="del_associated_thumbs" value="1" />
51
+ <span><?php _e('Delete Unselected Thumbnails','regenerate-thumbnails-advanced'); ?></span>
52
+ </label>
53
+ <div class='note'><p><?php _e('Delete thumbnails and metadata not selected in the settings. Will delete thumbnails from disk - be sure they are not in use. ','regenerate-thumbnails-advanced'); ?></p></div>
54
+ </div>
55
+ <div class='warning inline rta-notice rta_hidden' id='warn-delete-items'>
56
+ <div class='icon dashicons-info dashicons'></div>
57
+ <p><?php _e('Not selected thumbnails will be removed from your site. Check your settings if this is intentional.'); ?></p>
58
+
59
+ <p class='small'><?php _e('Regenerate Thumbnails Advanced will not prevent new media uploads from generating removed sizes', 'regenerate-thumbnails-advanced', 'regenerate-thumbnails-advanced'); ?></span></p>
60
  </div>
61
+
62
  <div class='option'>
63
+ <label for="del_leftover_metadata">
64
+ <input type="checkbox" name="del_leftover_metadata" id="del_leftover_metadata" value="1" />
65
+ <span><?php _e('Remove non-existent images','regenerate-thumbnails-advanced'); ?></span>
66
+ </label>
67
+ <div class='note'>
68
+ <p><?php _e('If the main image does not exist, removes this image, thumbnails and metadata','regenerate-thumbnails-advanced'); ?></p>
69
+ <p><?php _e('For removing images that are gone on disk, but still in media library', 'regenerate-thumbnails-advanced'); ?></p>
70
+ </div>
71
  </div>
72
+
73
  </div>
74
+ </div> <!-- container -->
75
  </section>
76
 
77
  <section class='form_controls'>
78
  <div class='container'>
79
+ <button type='submit' disabled class='rta_regenerate disabled'><?php _e('Regenerate', 'regenerate-thumbnails-advanced'); ?></button>
80
  <p class='save_note rta_hidden'><?php _e('Save your settings first','regenerate-thumbnails-advanced'); ?></p>
81
  </div>
82
  </section>
templates/admin/view_rta_settings.php CHANGED
@@ -73,7 +73,7 @@
73
  <div class='container'>
74
 
75
  <div class='option'>
76
- <label><?php _e('Use selected thumbnails:', 'regenerate-thumbnails-advanced') ?></label>
77
  <div class='checkbox-list'>
78
  <?php echo $view->generateImageSizeOptions($view->process_image_sizes); ?>
79
  </div>
@@ -81,8 +81,8 @@
81
  <span class='deselect' data-action='deselect' data-target='regenerate_sizes'><?php _e('Deselect All', 'regenerate-thumbnails-advanced'); ?></span>
82
  <div class='note'>
83
  <ul>
84
- <li><?php _e('Select the thumbnails you want to have available in your system. ', 'regenerate-thumbnails-advanced') ?></li>
85
- <li><?php printf(__('%s Keep existing %s will only generate missing thumbnails of your selected size', 'regenerate-thumbnails-advanced'), '<strong>','</strong>'); ?></li>
86
  </ul>
87
  </div>
88
 
73
  <div class='container'>
74
 
75
  <div class='option'>
76
+ <label><?php _e('Regenerate these thumbnails:', 'regenerate-thumbnails-advanced') ?></label>
77
  <div class='checkbox-list'>
78
  <?php echo $view->generateImageSizeOptions($view->process_image_sizes); ?>
79
  </div>
81
  <span class='deselect' data-action='deselect' data-target='regenerate_sizes'><?php _e('Deselect All', 'regenerate-thumbnails-advanced'); ?></span>
82
  <div class='note'>
83
  <ul>
84
+ <li><?php _e('Select the thumbnails you want to regenerate. ', 'regenerate-thumbnails-advanced') ?></li>
85
+ <li><?php printf(__('%s Don\'t redo existing %s - prevent regenerating images that already have these sizes as a thumbnail file. ', 'regenerate-thumbnails-advanced'), '<strong>','</strong>'); ?></li>
86
  </ul>
87
  </div>
88