reGenerate Thumbnails Advanced - Version 2.3.0

Version Description

Release date: 29th May 2020 * New system for queuing which should be more efficient; * New - Added regenerate thumbnails button in edit-attachment screen; * Fixed - Crash when regenerating image from edit media; * Fixed - Queries for large amount of images should not timeout; * Fixes for the responsiveness of the regeneration screen; * Class loader moved to PSR-4.

Download this release

Release Info

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

Code changes from version 2.2.0 to 2.3.0

Files changed (60) hide show
  1. README.md +0 -2
  2. build/shortpixel/PackageLoader.php +19 -4
  3. build/shortpixel/composer.json +1 -1
  4. build/shortpixel/log/src/ShortPixelLogger.php +6 -0
  5. build/shortpixel/notices/composer.json +1 -1
  6. build/shortpixel/notices/src/NoticeController.php +20 -5
  7. build/shortpixel/notices/src/NoticeModel.php +58 -4
  8. build/shortpixel/shortq/composer.json +18 -0
  9. build/shortpixel/shortq/src/DataProvider/DataProvider.php +27 -0
  10. build/shortpixel/shortq/src/DataProvider/MysqlDataProvider.php +485 -0
  11. build/shortpixel/shortq/src/Item.php +117 -0
  12. build/shortpixel/shortq/src/Queue/Queue.php +53 -0
  13. build/shortpixel/shortq/src/Queue/WPQ.php +545 -0
  14. build/shortpixel/shortq/src/ShortQ.php +71 -0
  15. build/shortpixel/shortq/src/Status.php +57 -0
  16. build/shortpixel/shortq/src/Tests/Tests.php +97 -0
  17. classes/Admin.php +160 -0
  18. classes/AjaxController.php +352 -0
  19. classes/{rta_admin_controller.php → Controllers/AdminController.php} +36 -69
  20. classes/{rta_controller.php → Controllers/Controller.php} +7 -9
  21. classes/{rta_front.php → Front.php} +2 -2
  22. classes/Image.php +443 -0
  23. classes/Install.php +34 -0
  24. classes/{rta-plugin.php → Plugin.php} +113 -46
  25. classes/Process.php +278 -0
  26. classes/controllers/rta_admin_controller.php +0 -264
  27. classes/plugin.json +1 -0
  28. classes/rta_admin.php +0 -695
  29. classes/rta_image.php +0 -244
  30. css/rta-admin-progress.css +35 -8
  31. css/rta-admin-view.css +61 -21
  32. css/rta.css +6 -0
  33. images/del.png +0 -0
  34. images/edit.png +0 -0
  35. images/pdf.png +0 -0
  36. images/robo-winky.png +0 -0
  37. images/view.png +0 -0
  38. includes/rta_class.php +0 -418
  39. includes/rta_install.php +0 -42
  40. includes/rta_uninstall.php +0 -26
  41. js/rta.js +117 -90
  42. js/rta.min.js +1 -1
  43. language/rta_general.php +0 -16
  44. readme.txt +12 -2
  45. regenerate-thumbnails-advanced.php +17 -15
  46. rta_admin.php +0 -497
  47. rta_front.php +0 -90
  48. scss/rta-admin-progress.scss +48 -11
  49. scss/rta-admin-view.scss +90 -21
  50. templates/admin/load_media_upload_js.php +0 -31
  51. templates/admin/rta_generate_thumbnails.php +9 -5
  52. templates/admin/rta_image_sizes.php +0 -84
  53. templates/admin/settings.php +0 -41
  54. templates/admin/view_ad.php +12 -0
  55. templates/admin/view_regenerate_process.php +15 -15
  56. templates/admin/view_rta_regenerate.php +8 -2
  57. templates/admin/view_rta_settings.php +19 -14
  58. templates/common/error.php +0 -3
  59. templates/common/message.php +0 -3
  60. templates/common/warning.php +0 -3
README.md DELETED
@@ -1,2 +0,0 @@
1
- # regenerate-thumbnails-advanced
2
- Generates Thumbnails for the old uploaded images according to the theme required image sizes - advanced functionality
 
 
build/shortpixel/PackageLoader.php CHANGED
@@ -4,18 +4,30 @@ namespace ReThumbAdvanced\Build;
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
  }
@@ -49,11 +61,13 @@ class PackageLoader
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)) {
@@ -62,6 +76,7 @@ class PackageLoader
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', '\\');
4
  class PackageLoader
5
  {
6
  public $dir;
7
+ public $composerFile = false;
8
 
9
+ public function __construct()
10
  {
11
+
12
+ }
13
+
14
+ public function setComposerFile($filePath)
15
+ {
16
+ $this->composerFile = json_decode(file_get_contents($filePath),1);
17
+ }
18
+
19
+ public function getComposerFile($filePath = false )
20
+ {
21
+ if (! $this->composerFile)
22
+ $this->composerFile = json_decode(file_get_contents($this->dir."/composer.json"), 1);
23
+
24
+ return $this->composerFile;
25
  }
26
 
27
  public function load($dir)
28
  {
29
  $this->dir = $dir;
30
  $composer = $this->getComposerFile();
 
 
31
  if(isset($composer["autoload"]["psr-4"])){
32
  $this->loadPSR4($composer['autoload']['psr-4']);
33
  }
61
  public function loadPSR($namespaces, $psr4)
62
  {
63
  $dir = $this->dir;
64
+
65
  // Foreach namespace specified in the composer, load the given classes
66
  foreach ($namespaces as $namespace => $classpaths) {
67
  if (!is_array($classpaths)) {
68
  $classpaths = array($classpaths);
69
  }
70
+
71
  spl_autoload_register(function ($classname) use ($namespace, $classpaths, $dir, $psr4) {
72
  // Check if the namespace matches the class we are looking for
73
  if (preg_match("#^".preg_quote($namespace)."#", $classname)) {
76
  $classname = str_replace($namespace, "", $classname);
77
  }
78
 
79
+
80
  // $filename = preg_replace("#\\\\#", "", $classname).".php";
81
  // This is fix for nested classes which were losing a /
82
  $filename = ltrim($classname .'.php', '\\');
build/shortpixel/composer.json CHANGED
@@ -1 +1 @@
1
- {"name":"ReThumbAdvanced\/shortpixelmodules","description":"ShortPixel submodules","type":"function","autoload":{"psr-4":{"ReThumbAdvanced\\ShortPixelLogger":"log\/src","ReThumbAdvanced\\Notices":"notices\/src"}}}
1
+ {"name":"ReThumbAdvanced\/shortpixelmodules","description":"ShortPixel submodules","type":"function","autoload":{"psr-4":{"ReThumbAdvanced\\ShortPixelLogger":"log\/src","ReThumbAdvanced\\Notices":"notices\/src","ReThumbAdvanced\\ShortQ":"shortq\/src"}}}
build/shortpixel/log/src/ShortPixelLogger.php CHANGED
@@ -250,6 +250,12 @@ namespace ReThumbAdvanced\ShortPixelLogger;
250
  $log->addLog($message, $level, $args);
251
  }
252
 
 
 
 
 
 
 
253
  public static function logLevel($level)
254
  {
255
  $log = self::getInstance();
250
  $log->addLog($message, $level, $args);
251
  }
252
 
253
+ /** These should be removed every release. They are temporary only for d'bugging the current release */
254
+ public static function addTemp($message, $args = array())
255
+ {
256
+ self::addDebug($message, $args);
257
+ }
258
+
259
  public static function logLevel($level)
260
  {
261
  $log = self::getInstance();
build/shortpixel/notices/composer.json CHANGED
@@ -1,7 +1,7 @@
1
  {
2
  "name": "shortpixel/notices",
3
  "description": "ShortPixel WordPress Notice System",
4
- "version": "1.3",
5
  "type": "library",
6
  "license": "MIT",
7
  "authors": [
1
  {
2
  "name": "shortpixel/notices",
3
  "description": "ShortPixel WordPress Notice System",
4
+ "version": "1.5",
5
  "type": "library",
6
  "license": "MIT",
7
  "authors": [
build/shortpixel/notices/src/NoticeController.php CHANGED
@@ -65,8 +65,6 @@ class NoticeController //extends ShortPixelController
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
  {
@@ -90,7 +88,7 @@ class NoticeController //extends ShortPixelController
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;
@@ -141,6 +139,7 @@ class NoticeController //extends ShortPixelController
141
  public function getNoticesForDisplay()
142
  {
143
  $newNotices = array();
 
144
  foreach(self::$notices as $notice)
145
  {
146
  if ($notice->isDismissed()) // dismissed never displays.
@@ -266,7 +265,23 @@ class NoticeController //extends ShortPixelController
266
 
267
  }
268
 
269
- public static function makePersistent($notice, $key, $suppress = -1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
270
  {
271
  $noticeController = self::getInstance();
272
  $existing = $noticeController->getNoticeByID($key);
@@ -291,7 +306,7 @@ class NoticeController //extends ShortPixelController
291
  }
292
  else
293
  {
294
- $notice->setPersistent($key, $suppress); // set this notice persistent.
295
  }
296
 
297
  $noticeController->update();
65
  {
66
  $notices = get_option($this->notice_option, false);
67
  $cnotice = (is_array($notices)) ? count($notices) : 0;
 
 
68
 
69
  if ($notices !== false && is_array($notices))
70
  {
88
  foreach(self::$notices as $nitem)
89
  {
90
  if ($nitem->message == $notice->message && $nitem->code == $notice->code) // same message.
91
+ return $nitem; // return the notice with the same message.
92
  }
93
  }
94
  self::$notices[] = $notice;
139
  public function getNoticesForDisplay()
140
  {
141
  $newNotices = array();
142
+
143
  foreach(self::$notices as $notice)
144
  {
145
  if ($notice->isDismissed()) // dismissed never displays.
265
 
266
  }
267
 
268
+ public static function addDetail($notice, $detail)
269
+ {
270
+ $noticeController = self::getInstance();
271
+ $notice->addDetail($detail);
272
+
273
+ // $notice_id = spl_object_id($notice);
274
+
275
+ $noticeController->update();
276
+ }
277
+
278
+ /** Make a regular notice persistent across multiple page loads
279
+ * @param $notice NoticeModel The Notice to make Persistent
280
+ * @param $key String Identifier of the persistent notice.
281
+ * @param $suppress Int When dismissed, time to stay dismissed
282
+ * @param $callback Function Callable function
283
+ */
284
+ public static function makePersistent($notice, $key, $suppress = -1, $callback = null)
285
  {
286
  $noticeController = self::getInstance();
287
  $existing = $noticeController->getNoticeByID($key);
306
  }
307
  else
308
  {
309
+ $notice->setPersistent($key, $suppress, $callback); // set this notice persistent.
310
  }
311
 
312
  $noticeController->update();
build/shortpixel/notices/src/NoticeModel.php CHANGED
@@ -4,6 +4,7 @@ namespace ReThumbAdvanced\Notices;
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.
@@ -16,6 +17,7 @@ class NoticeModel //extends ShortPixelModel
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
 
@@ -82,16 +84,33 @@ class NoticeModel //extends ShortPixelModel
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)
@@ -122,6 +141,13 @@ class NoticeModel //extends ShortPixelModel
122
 
123
  $icon = '';
124
 
 
 
 
 
 
 
 
125
  switch($this->messageType)
126
  {
127
  case self::NOTICE_ERROR:
@@ -158,9 +184,24 @@ class NoticeModel //extends ShortPixelModel
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>";
@@ -169,6 +210,19 @@ class NoticeModel //extends ShortPixelModel
169
 
170
  }
171
 
 
 
 
 
 
 
 
 
 
 
 
 
 
172
  private function getDismissJS()
173
  {
174
  $url = wp_json_encode(admin_url('admin-ajax.php'));
@@ -179,7 +233,7 @@ class NoticeModel //extends ShortPixelModel
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;
4
  class NoticeModel //extends ShortPixelModel
5
  {
6
  public $message; // The message we want to convey.
7
+ public $details = array(); // extra details, like the files involved. Something could be hideable in the future.
8
  public $code;
9
 
10
  private $id = null; // used for persistent messages.
17
  public $messageType = self::NOTICE_NORMAL;
18
 
19
  public $notice_action; // empty unless for display. Ajax action to talk back to controller.
20
+ protected $callback; // empty unless callback is needed
21
 
22
  public static $icons = array();
23
 
84
  $this->suppress_until = $timestamp;
85
  }
86
 
87
+ /** Support for extra information beyond the message.
88
+ * Can help to not overwhelm users w/ the same message but different file /circumstances.
89
+ */
90
+ public function addDetail($detail, $clean = false)
91
+ {
92
+ if ($clean)
93
+ $this->details = array();
94
+
95
+ if (! in_array($detail, $this->details) )
96
+ $this->details[] = $detail;
97
+ }
98
+
99
+
100
 
101
  /** Set a notice persistent. Meaning it shows every page load until dismissed.
102
  * @param $key Unique Key of this message. Required
103
  * @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
104
  */
105
+ public function setPersistent($key, $suppress = -1, $callback = null)
106
  {
107
  $this->id = $key;
108
  $this->is_persistent = true;
109
  $this->suppress_period = $suppress;
110
+ if ( ! is_null($callback) && is_callable($callback))
111
+ {
112
+ $this->callback = $callback;
113
+ }
114
  }
115
 
116
  public static function setIcon($notice_type, $icon)
141
 
142
  $icon = '';
143
 
144
+ if ($this->callback)
145
+ {
146
+ $return = call_user_func($this->callback, $this);
147
+ if ($return === false) // don't display is callback returns false explicitly.
148
+ return;
149
+ }
150
+
151
  switch($this->messageType)
152
  {
153
  case self::NOTICE_ERROR:
184
  $class .= 'is-persistent ';
185
  }
186
 
187
+ $id = ! is_null($this->id) ? $this->id : uniqid();
188
+ //'id="' . $this->id . '"'
189
+ $output = "<div id='$id' class='$class'><span class='icon'> " . $icon . "</span> <span class='content'>" . $this->message;
190
+ if ($this->hasDetails())
191
+ {
192
+ $output .= '<div class="details-wrapper">
193
+ <input type="checkbox" name="detailhider" id="check-' . $id .'">
194
+ <label for="check-' . $id . '" class="show-details"><span>' . __('See Details', 'shortpixel-image-optimiser') . '</span>
195
+ </label>';
196
+
197
+ $output .= "<div class='detail-content-wrapper'><p class='detail-content'>" . $this->parseDetails() . "</p></div>";
198
+ $output .= '<label for="check-' . $id . '" class="hide-details"><span>' . __('Hide Details', 'shortpixel-image-optimiser') . '</span></label>';
199
+
200
+ $output .= '</div>'; // detail rapper
201
+
202
+ }
203
+ $output .= "</span></div>";
204
 
 
205
  if ($this->is_persistent && $this->is_removable)
206
  {
207
  $output .= "<script type='text/javascript'>\n" . $this->getDismissJS() . "\n</script>";
210
 
211
  }
212
 
213
+ protected function hasDetails()
214
+ {
215
+ if (is_array($this->details) && count($this->details) > 0)
216
+ return true;
217
+ else
218
+ return false;
219
+ }
220
+
221
+ protected function parseDetails()
222
+ {
223
+ return implode('<BR>', $this->details);
224
+ }
225
+
226
  private function getDismissJS()
227
  {
228
  $url = wp_json_encode(admin_url('admin-ajax.php'));
233
 
234
  // $data_string = "{action:'$this->notice_action'}";
235
 
236
+ $js = "jQuery(document).on('click','#$this->id button.notice-dismiss',
237
  function() {
238
  var data = $data;
239
  var url = $url;
build/shortpixel/shortq/composer.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "shortpixel/shortq",
3
+ "description": "Simple Queue",
4
+ "version": 0.5,
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\\ShortQ\\" : "src" }
17
+ }
18
+ }
build/shortpixel/shortq/src/DataProvider/DataProvider.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace ReThumbAdvanced\ShortQ\DataProvider;
3
+ use ReThumbAdvanced\ShortQ\Item as Item;
4
+
5
+
6
+ /* DataProvider handles where the data is stored, and retrieval upon queue request
7
+ *
8
+ * DataProvider is responsible for creating it's own environment, and cleanup when uninstall is being called.
9
+ *
10
+ */
11
+ interface DataProvider
12
+ {
13
+
14
+ function __construct($pluginSlug, $queueName);
15
+
16
+ //function add($items);
17
+ function enqueue($items);
18
+ function dequeue($args); // @return Items removed from queue and set to status. Returns Item Object
19
+ function alterqueue($args); // @return Item Count / Boolean . Mass alteration of queue.
20
+ function itemUpdate(Item $item, $new_status);
21
+
22
+ // Returns number of items left in Queue.
23
+ function itemCount($mode = 'waiting');
24
+
25
+ function install();
26
+ function uninstall();
27
+ }
build/shortpixel/shortq/src/DataProvider/MysqlDataProvider.php ADDED
@@ -0,0 +1,485 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace ReThumbAdvanced\ShortQ\DataProvider;
3
+ use ReThumbAdvanced\ShortQ\Item as Item;
4
+ use ReThumbAdvanced\ShortQ\ShortQ as ShortQ;
5
+
6
+
7
+ /* WP Mysql DataProvider
8
+ *
9
+ */
10
+ class MysqlDataProvider implements DataProvider
11
+ {
12
+ protected $qName; // Limit is 30 chars!
13
+ protected $slug; // Limit is 30 chars!
14
+
15
+ protected $table;
16
+
17
+ protected $query_size_limit = 10000; // in strlen characters.
18
+
19
+ /* Constructor */
20
+ public function __construct($slug, $qName)
21
+ {
22
+ global $wpdb;
23
+ $this->slug = $slug;
24
+ $this->qName = $qName;
25
+
26
+ $this->table = $wpdb->prefix . 'shortpixel_queue';
27
+ }
28
+
29
+ public function enqueue($items)
30
+ {
31
+ global $wpdb;
32
+ if (! is_array($items))
33
+ return false;
34
+ // start higher to allow priority additions easily.
35
+ $list_order = (10 + $this->itemCount());
36
+ $now = date('Y-m-d H:i:s');
37
+
38
+ $sql = 'INSERT IGNORE INTO ' . $this->table . ' (queue_name, plugin_slug, value, list_order, item_id, updated, created) VALUES ';
39
+ $values = array();
40
+ foreach ($items as $item)
41
+ {
42
+ $item_id = (int) $item->item_id;
43
+ $value = $item->getRaw('value'); // value;
44
+
45
+ $order = (! is_null($item->list_order)) ? $item->list_order : $list_order;
46
+
47
+ $values[] = $wpdb->prepare('(%s, %s, %s, %d, %d, %s, %s)', $this->qName, $this->slug, $value, $order, $item_id, $now, $now);
48
+ if (! isset($item->list_order))
49
+ $list_order++;
50
+
51
+ }
52
+ $sql .= implode( ",\n", $values );
53
+ $result = $wpdb->query($sql, $values);
54
+
55
+ if (! $this->checkQueryOK())
56
+ {
57
+ return false;
58
+ }
59
+
60
+ return $result;
61
+ }
62
+
63
+ /* Check item consistency and check if items are not already in this queue. Must be unique */
64
+ protected function prepareItems($items)
65
+ {
66
+ global $wpdb;
67
+
68
+ $items_ids = array();
69
+ foreach($items as $key => $item)
70
+ {
71
+ if (isset($item['id']))
72
+ $items_ids[] = $item['id'];
73
+ else // no id, no q
74
+ unset($items[$key]);
75
+ }
76
+ }
77
+
78
+ /* Dequeue an item (return it) via specific parameters. Sets a new status after grabbing these records.
79
+ *
80
+ * @param $args Array
81
+ numitems - number of records to pull
82
+ status - Array - the statusses to pull
83
+ newstatus - To which status said items should be put
84
+ orderby - how to order the records [not implemented]
85
+
86
+ @return Recordset of Items gotten.
87
+ */
88
+ public function dequeue($args = array())
89
+ {
90
+ $defaults = array(
91
+ 'numitems' => 1, // pass -1 for all.
92
+ 'status' => ShortQ::QSTATUS_WAITING,
93
+ 'newstatus' => ShortQ::QSTATUS_DONE,
94
+ 'orderby' => 'list_order',
95
+ 'order' => 'ASC',
96
+ );
97
+
98
+ $args = wp_parse_args($args, $defaults);
99
+
100
+ if (is_array($args['status']))
101
+ $args['status'] = implode(',', $args['status']);
102
+
103
+ $items = $this->queryItems(array(
104
+ 'numitems' => $args['numitems'],
105
+ 'status' => $args['status'],
106
+ 'orderby' => $args['orderby'],
107
+ 'order' => $args['order'],
108
+ ));
109
+
110
+ $id_array = array_keys($items);
111
+
112
+ // Update status if results yielded.
113
+ if ($args['status'] !== $args['newstatus'] && count($id_array) > 0)
114
+ {
115
+ $now = time();
116
+ $this->updateRecords(array('status' => $args['newstatus'], 'updated' => $now ), array('id' => $id_array));
117
+ foreach($items as $index => $item)
118
+ {
119
+ $item->status = $args['newstatus']; // update status to new situation.
120
+ $item->updated = $now;
121
+ $items[$index] = $item;
122
+ }
123
+ }
124
+ if ($args['newstatus'] == ShortQ::QSTATUS_DELETE)
125
+ {
126
+ $this->removeRecords(array('status' => ShortQ::QSTATUS_DELETE));
127
+ }
128
+ // @todo is Status = QSTATUS_DELETE, remove all records after putting them to this status.
129
+
130
+ return array_values($items); // array values resets the id index returns by queryItems
131
+ }
132
+
133
+
134
+
135
+ private function queryItems($args = array())
136
+ {
137
+ $defaults = array(
138
+ 'status' => ShortQ::QSTATUS_ALL,
139
+ 'orderby' => 'list_order',
140
+ 'order' => 'ASC',
141
+ 'numitems' => -1,
142
+ );
143
+
144
+ $args = wp_parse_args($args, $defaults);
145
+
146
+ global $wpdb;
147
+ $prepare = array();
148
+
149
+ $sql = 'SELECT * from ' . $this->table . ' where queue_name = %s and plugin_slug = %s ';
150
+ $prepare[] = $this->qName;
151
+ $prepare[] = $this->slug;
152
+
153
+ if ($args['status'] <> ShortQ::QSTATUS_ALL)
154
+ {
155
+ $sql .= 'and status = %d ';
156
+ $prepare[] = $args['status'];
157
+ }
158
+
159
+ if ($args['orderby'])
160
+ {
161
+ $order = (strtoupper($args['order']) == 'ASC') ? 'ASC ' : 'DESC ';
162
+ $sql .= 'order by ' . $args['orderby'] . ' ' . $order;
163
+
164
+ // $prepare[] = $args['orderby'];
165
+ }
166
+
167
+ if ($args['numitems'] > 0)
168
+ {
169
+ $sql .= 'limit %d ';
170
+ $prepare[] = $args['numitems'];
171
+ }
172
+
173
+ $sql = $wpdb->prepare($sql, $prepare);
174
+
175
+ $result = $wpdb->get_results($sql, ARRAY_A);
176
+
177
+ $items = array();
178
+
179
+ foreach($result as $index => $row)
180
+ {
181
+ $item = new Item();
182
+ $id = $row['id'];
183
+ foreach($row as $name => $value)
184
+ {
185
+ if (property_exists($item, $name))
186
+ {
187
+ $item->$name = $value;
188
+ }
189
+ }
190
+ $items[$id] = $item;
191
+ }
192
+
193
+ return $items;
194
+ }
195
+
196
+ /** Updates a set of items from queue without pulling or returning those records.
197
+ *
198
+ * @return int Number of Records Updated
199
+ */
200
+ public function alterqueue($args)
201
+ {
202
+
203
+ }
204
+
205
+ /** Updates one queued item, for instance in case of failing, or status update
206
+ *
207
+ * @param $item_id int The Uniq Id of the item to update
208
+ * @param $field Array An array of fields in key => pair format to be updated.
209
+ */
210
+ public function itemUpdate(Item $item, $fields)
211
+ {
212
+ $result = $this->updateRecords($fields, array('item_id' => $item->item_id));
213
+ if ($result == 1 )
214
+ return true;
215
+ else
216
+ return false;
217
+ }
218
+
219
+
220
+ /* Counts Items in Database Queue
221
+ * @param Status Mixed When supplied with ShortQ Status Constant it will count this status, will count all with ShortQ:QSTATUS_ALL.
222
+ * When given 'countbystatus' it will return an array with ShortQ Status as key and the count as value
223
+ @return Mixed Either count int, or Array.
224
+ */
225
+ public function itemCount($status = ShortQ::QSTATUS_WAITING)
226
+ {
227
+ global $wpdb;
228
+ if (is_numeric($status) && $status != ShortQ::QSTATUS_ALL)
229
+ {
230
+ $sql = 'SELECT count(*) FROM ' . $this->table . ' WHERE queue_name = %s and plugin_slug = %s and status = %d ';
231
+ $count = $wpdb->get_var($wpdb->prepare($sql, $this->qName, $this->slug, $status));
232
+ }
233
+ elseif ($status == ShortQ::QSTATUS_ALL) // full queue, with records from all status.
234
+ {
235
+ $sql = 'SELECT count(*) FROM ' . $this->table . ' WHERE queue_name = %s and plugin_slug = %s ';
236
+ $count = $wpdb->get_var($wpdb->prepare($sql, $this->qName, $this->slug));
237
+ }
238
+ elseif ($status == 'countbystatus')
239
+ {
240
+ $sql = 'SELECT count(id) as count, status FROM ' . $this->table . ' WHERE queue_name = %s and plugin_slug = %s group by status';
241
+ $rows = $wpdb->get_results($wpdb->prepare($sql, $this->qName, $this->slug), ARRAY_A);
242
+ $count = array();
243
+
244
+ foreach($rows as $row)
245
+ {
246
+ $count[$row['status']] = $row['count'];
247
+ }
248
+
249
+
250
+ }
251
+
252
+ if (!empty($wpdb->last_error))
253
+ {
254
+ $this->handleError($wpdb->last_error);
255
+ return 0;
256
+ }
257
+
258
+ return $count;
259
+ }
260
+
261
+ /** Update records
262
+ *
263
+ * @param $Data Array. Data array to change, to WP standards
264
+ * @param $where Array. Data Array on conditions, to WP standards
265
+ * @return int Amount of records updates, or null|false
266
+ */
267
+ private function updateRecords($data, $where)
268
+ {
269
+ global $wpdb;
270
+ $update_sql = 'UPDATE ' . $this->table . ' set updated = %s';
271
+ if (isset($data['updated']))
272
+ {
273
+ $placeholders = array($data['updated']);
274
+ unset($data['updated']);
275
+ }
276
+ else
277
+ $placeholders = array(date('Y-m-d H:i:s'));
278
+
279
+ foreach($data as $field => $value)
280
+ {
281
+ $update_sql .= ' ,' . $field . ' = %s ';
282
+ $placeholders[] = $value;
283
+ }
284
+
285
+ $update_sql .= ' WHERE queue_name = %s and plugin_slug = %s ';
286
+ $placeholders[] = $this->qName;
287
+ $placeholders[] = $this->slug;
288
+
289
+ foreach ($where as $field => $value)
290
+ {
291
+ if (is_array($value))
292
+ {
293
+ $vals = implode( ', ', array_fill( 0, count( $value ), '%s' ));
294
+ $update_sql .= ' AND ' . $field . ' in (' . $vals . ' ) ';
295
+ $placeholders = array_merge($placeholders, $value);
296
+ }
297
+ else {
298
+ $update_sql .= ' AND ' . $field . ' = %s';
299
+ $placeholders[] = $value;
300
+ }
301
+ }
302
+ $update_sql = $wpdb->prepare($update_sql, $placeholders);
303
+
304
+ $result = $wpdb->query($update_sql);
305
+ return $result;
306
+ }
307
+
308
+ /** @todo Accept array or ItemIDS to remove
309
+ * @param $args Array . Array of options:
310
+ * 'Status' : remove items with selected ShortQ QSTATUS
311
+ * 'All' : Set to true to remove all from this queue ( sep. argument is safety feature )
312
+ * 'Item_id' : Delete by this item id
313
+ * 'Items' : Array of Item ID's.
314
+ */
315
+ public function removeRecords($args)
316
+ {
317
+ $defaults = array(
318
+ 'status' => null,
319
+ 'all' => false,
320
+ 'item_id' => null,
321
+ 'items' => null,
322
+ );
323
+
324
+ global $wpdb;
325
+ $args = wp_parse_args($args, $defaults);
326
+
327
+ $data = array($this->qName, $this->slug);
328
+ $delete_sql = 'DELETE FROM ' . $this->table . ' where queue_name = %s and plugin_slug = %s';
329
+
330
+ if (! is_null($args['status']))
331
+ {
332
+ $data[] = intval($args['status']);
333
+ $delete_sql .= ' and status = %s';
334
+ }
335
+ elseif (! is_null($args['item_id']))
336
+ {
337
+ $data[] = $args['item_id'];
338
+ $delete_sql .= ' and item_id = %s';
339
+ }
340
+ elseif(! is_null($args['items']) && count($args['items']) > 0)
341
+ {
342
+ $items = $args['items'];
343
+ $vals = implode( ', ', array_fill( 0, count( $items ), '%s' ));
344
+ $delete_sql .= ' AND item_id in (' . $vals . ' ) ';
345
+ $data = array_merge($data, $items);
346
+ }
347
+ elseif ($args['all'] === true)
348
+ {
349
+ // do nothing, query already here for full delete.
350
+ }
351
+ else {
352
+ return false; // prevent accidents if all is not set explicitly.
353
+ }
354
+
355
+ $result = $wpdb->query($wpdb->prepare($delete_sql, $data));
356
+
357
+ return $result;
358
+ }
359
+
360
+ /** Checks if database table properly exists
361
+ * https://wordpress.stackexchange.com/questions/220275/wordpress-unit-testing-cannot-create-tables
362
+ * @return Boolean Yes or no
363
+ */
364
+ private function check()
365
+ {
366
+ global $wpdb;
367
+ $sql = $wpdb->prepare("
368
+ SHOW TABLES LIKE %s
369
+ ", $this->table);
370
+
371
+ $result = intval($wpdb->query($sql));
372
+
373
+ if ($result == 0)
374
+ return false;
375
+ else {
376
+ return true;
377
+ }
378
+ // if something something, install.
379
+ }
380
+
381
+ public function install()
382
+ {
383
+ if ($this->check())
384
+ return true;
385
+
386
+ require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
387
+
388
+ global $wpdb;
389
+
390
+ $charset = $wpdb->get_charset_collate();
391
+ $sql = "CREATE TABLE `" . $this->table . "` (
392
+ id INT UNSIGNED NOT NULL AUTO_INCREMENT,
393
+ queue_name VARCHAR(30) NOT NULL,
394
+ plugin_slug VARCHAR(30) NOT NULL,
395
+ status int(11) NOT NULL DEFAULT 0,
396
+ list_order int(11) NOT NULL,
397
+ item_id INT NOT NULL,
398
+ value longtext NOT NULL,
399
+ tries int(11) NOT NULL DEFAULT 0,
400
+ created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
401
+ updated timestamp NULL DEFAULT CURRENT_TIMESTAMP,
402
+ PRIMARY KEY (id),
403
+ INDEX queue_name (queue_name),
404
+ INDEX plugin_slug (plugin_slug),
405
+ INDEX status (status),
406
+ INDEX item_id (item_id),
407
+ INDEX list_order (list_order)
408
+ ) $charset; ";
409
+
410
+ $result = dbDelta($sql);
411
+
412
+
413
+
414
+ $sql = "SHOW INDEX FROM " . $this->table . " WHERE Key_name = 'uq'";
415
+ $result = $wpdb->get_results($sql);
416
+ if (is_null($result) || count($result) == 0)
417
+ {
418
+ $sql = 'ALTER TABLE '. $this->table . ' ADD CONSTRAINT UNIQUE uq(plugin_slug,queue_name,item_id)';
419
+ $wpdb->query($sql);
420
+ }
421
+
422
+ return $this->check();
423
+ }
424
+
425
+ public function uninstall()
426
+ {
427
+ global $wpdb;
428
+ require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
429
+
430
+ // Check if table exists, if not, return.
431
+ if (! $this->check())
432
+ return false;
433
+
434
+ $sql = 'SELECT count(*) as cnt FROM ' . $this->table;
435
+ $records = $wpdb->get_var($sql);
436
+
437
+
438
+ // Don't remove table on any doubt.
439
+ if (is_null($records) || intval($records) <> 0)
440
+ return false;
441
+
442
+ $sql = ' DROP TABLE IF EXISTS ' . $this->table;
443
+
444
+ $wpdb->query($sql);
445
+ // dbDelta($sql);
446
+
447
+ return $this->check();
448
+ }
449
+
450
+ private function checkQueryOK($override_check = false)
451
+ {
452
+ global $wpdb;
453
+
454
+ if (!empty($wpdb->last_error))
455
+ {
456
+ $this->handleError($wpdb->last_error, $override_check);
457
+ return false;
458
+ }
459
+
460
+ return true;
461
+ }
462
+
463
+ private function handleError($error, $override_check = false)
464
+ {
465
+ global $wpdb;
466
+
467
+ // check if table is there.
468
+ if (! $override_check)
469
+ {
470
+ if (! $this->check())
471
+ $this->install();
472
+ }
473
+
474
+ echo "<PRE> ERROR! ";
475
+ print_r( debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2) );
476
+ echo ($wpdb->last_query);
477
+ var_dump($error);
478
+ echo "</PRE>";
479
+ $this->install();
480
+
481
+ // @todo Add error log here
482
+ }
483
+
484
+
485
+ }
build/shortpixel/shortq/src/Item.php ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace ReThumbAdvanced\ShortQ;
3
+
4
+ /* The Queue Item
5
+ *
6
+ * The items must correspond 1-on-1 with Storage Items invoked
7
+ */
8
+ class Item
9
+ {
10
+
11
+ protected $id;
12
+ protected $created; // as a timestamp
13
+ protected $updated; // as a timestamp
14
+ protected $item_id; // the item id of the processor.
15
+ protected $value; // something of value to the processor
16
+ protected $json_was_array;
17
+ protected $status = 0;
18
+ protected $list_order;
19
+ protected $tries = 0;
20
+
21
+ public function __construct()
22
+ {
23
+
24
+ }
25
+
26
+ // Without magic conversion. Used for methods such as database insertion of value
27
+ public function getRaw($name)
28
+ {
29
+ if (isset($this->$name))
30
+ return $this->$name;
31
+
32
+ return null;
33
+ }
34
+
35
+ public function __get($name)
36
+ {
37
+ $value= null;
38
+
39
+ switch($name)
40
+ {
41
+ case 'value':
42
+ case 'json_was_array':
43
+ if ($this->isJson($this->value))
44
+ {
45
+ $jsonObj = json_decode($this->value);
46
+ $this->json_was_array = $jsonObj->was_array;
47
+
48
+ if ($name == 'value')
49
+ {
50
+ if ($this->json_was_array) // since it's being set after decode, redo this.
51
+ { $json_array = json_decode($this->value, $this->json_was_array);
52
+ $value = $json_array['value'];
53
+ }
54
+ else
55
+ {
56
+ $value = $jsonObj->value;
57
+ }
58
+ }
59
+ elseif($name = 'json_was_array') // this is an internal item that normally shouldn't be requested.
60
+ $value = $jsonObj->was_array;
61
+ }
62
+ elseif (isset($this->$name))
63
+ $value = $this->$name;
64
+ break;
65
+ default:
66
+ {
67
+ if (isset($this->$name))
68
+ $value = $this->$name;
69
+ }
70
+ }
71
+
72
+ return $value;
73
+ }
74
+
75
+ public function __set($name, $value)
76
+ {
77
+ switch($name)
78
+ {
79
+ case 'created':
80
+ case 'updated':
81
+ if (! is_numeric($value))
82
+ $value = strtotime($value);
83
+
84
+ $this->$name = $value;
85
+ break;
86
+ case 'value':
87
+ if (is_array($value) || is_object($value))
88
+ {
89
+ $this->json_was_array = (is_array($value)) ? true : false;
90
+ $jsonObj = new \stdClass;
91
+ $jsonObj->was_array = $this->json_was_array;
92
+ $jsonObj->value = $value;
93
+
94
+ $value = json_encode($jsonObj);
95
+ }
96
+
97
+ $this->$name = $value;
98
+ break;
99
+ default:
100
+ if (property_exists($this, $name))
101
+ $this->$name = $value;
102
+ break;
103
+ }
104
+
105
+ return $this;
106
+ }
107
+
108
+ private function isJson($value)
109
+ {
110
+ if (is_int($value) || is_numeric($value)) // solo-integer is not a json but will validate.
111
+ return false;
112
+
113
+ json_decode($value);
114
+ return (json_last_error() == JSON_ERROR_NONE);
115
+ }
116
+
117
+ }
build/shortpixel/shortq/src/Queue/Queue.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace ReThumbAdvanced\ShortQ\Queue;
3
+ use ReThumbAdvanced\ShortQ\Item as Item;
4
+
5
+
6
+
7
+ /* Needed features
8
+ - Database / Table agnostic Queue system (as in not dependent on specific ID's).
9
+ - Check if Queue is in Use / Lock system
10
+ - Multiple ways to say / restore should be possible
11
+ - Multiplugin ready
12
+ */
13
+
14
+ /* Queue is the main iterator for the queue */
15
+ interface Queue
16
+ {
17
+
18
+ // needs to sync with DataProvider!
19
+ const QSTATUS_WAITING = 0; //Waiting for process
20
+ const QSTATUS_PULLED = 1;
21
+ const QSTATUS_INPROCESS = 2; // Doing process now
22
+ const QSTATUS_DONE = 3; // Is Done.
23
+
24
+ const QSTATUS_DELETE = -1; // this is a virtual status. If set to this, will be deleted.
25
+ const QSTATUS_ERROR = -2;
26
+ const QSTATUS_FATAL = -3;
27
+ //private $name; // queue name
28
+
29
+ public function __construct($pluginSlug, $queue_name, $dataProvider);
30
+ public function setOptions($options); // set options via array, such as how much to pull / type of queue
31
+
32
+ /* @param Mixed $items Items, or array of items. */
33
+ public function addItems($items);
34
+ public function enqueue();
35
+ public function withOrder($items, $order); // chained method for adding items with an order. Returns Queue Object
36
+ public function dequeue();
37
+
38
+ /** Functions for async processing. Process should return item_id, put them on done or fail. */
39
+ public function itemDone(Item $item);
40
+ public function itemFailed(Item $item, $fatal = false);
41
+
42
+ // return status object, for app to check what is going on.
43
+ public function getStatus();
44
+
45
+
46
+
47
+ public function hasItems();
48
+ public function itemCount();
49
+
50
+ //public function setDataProvider($DataProvider); // DataProvider Object
51
+ public function uninstall();
52
+
53
+ } // class
build/shortpixel/shortq/src/Queue/WPQ.php ADDED
@@ -0,0 +1,545 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace ReThumbAdvanced\ShortQ\Queue;
3
+ use ReThumbAdvanced\ShortQ\Item as Item;
4
+ use \ReThumbAdvanced\ShortQ\Status as Status;
5
+ use \ReThumbAdvanced\ShortQ\ShortQ as ShortQ;
6
+
7
+ class WPQ implements Queue
8
+ {
9
+ private $statusName = 'shortqwp_';
10
+
11
+ protected $qName; // queue Name
12
+ protected $pSlug; // plugin slug
13
+ protected $DataProvider;
14
+
15
+ protected $status;
16
+ protected $items = array();
17
+
18
+ protected $options;
19
+
20
+ // statistics and status
21
+ protected $current_ask = 0;
22
+
23
+ /*
24
+ * @param qName - Name of the Queue requested by parent
25
+ */
26
+ public function __construct($slug, $qName, $DataProvider)
27
+ {
28
+ if ($slug == '' || $qName == '' )
29
+ return false;
30
+
31
+ $statusName = $this->statusName . $slug;
32
+ if (strlen($statusName) >= 64) // max for wp_options
33
+ $statusName = substr($statusName, 0, 64);
34
+
35
+ $this->statusName = $statusName;
36
+
37
+ $this->qName = $qName;
38
+ $this->pSlug = $slug;
39
+ $this->DataProvider = $DataProvider;
40
+
41
+ $this->loadStatus();
42
+
43
+ $this->options = new \stdclass;
44
+ $this->options->numitems = 1; //amount to dequeue
45
+ $this->options->mode = 'direct'; // direct | wait
46
+ $this->options->enqueue_limit = 1000; // amount of items to deliver to DataProvider in one go.
47
+ $this->options->process_timeout = 10000; //How long to wait 'IN_PROCESS' for a retry to happen (until retry_limit)
48
+ $this->options->retry_limit = 5;
49
+ $this->options->timeout_recount = 20000; // Time to recount and check stuff from datasource in MS
50
+ $this->options->is_debug = false;
51
+
52
+ }
53
+
54
+ public function setOptions($options)
55
+ {
56
+ foreach($options as $option => $value)
57
+ {
58
+ $this->setOption($option, $value);
59
+ }
60
+ }
61
+
62
+ public function setOption($name, $value)
63
+ {
64
+ if (property_exists($this->options, $name))
65
+ $this->options->$name = $value;
66
+ }
67
+
68
+ public function getOption($name)
69
+ {
70
+ if (property_exists($this->options, $name))
71
+ return $this->options->$name;
72
+ }
73
+
74
+ /** Prepare items for enqueue, if you want to deliver items in batch, but not flush to storage directly
75
+ * Every Item needs to have an (item)_id and (item)_value. That's the only thing remote app should be aware of.
76
+ * @param Array Item Array with fields: id, value [order]
77
+ *
78
+ *
79
+ */
80
+ public function addItems($items)
81
+ {
82
+ foreach($items as $item)
83
+ {
84
+
85
+ if (! isset($item['id']))
86
+ continue;
87
+
88
+ $value = isset($item['value']) ? $item['value'] : '';
89
+ $itemObj = new Item();
90
+ $itemObj->item_id = $item['id'];
91
+ $itemObj->value = $value;
92
+
93
+ if (isset($item['order']))
94
+ $itemObj->list_order = $item['order'];
95
+
96
+ $this->items[] = $itemObj;
97
+
98
+ }
99
+ if (count($items) > 0)
100
+ {
101
+ $this->setStatus('preparing', true, false);
102
+ $this->setStatus('finished', false, false); // can't be finished when adding items.
103
+ }
104
+ }
105
+
106
+ /** Simple Enqueue.
107
+ * @param $items Array List of Items to add, see @AddItems
108
+ * @return int $numItems Number of Items in this Queue [Total]
109
+ * Note that each addition does a save of option retaining the last_item_id. Ideally add as many items that can fit in memory / time limit constraints
110
+ */
111
+ public function enqueue($items = array() )
112
+ {
113
+ if (count($items) > 0)
114
+ $this->addItems($items);
115
+
116
+ $chunks = array_chunk($this->items, $this->options->enqueue_limit );
117
+ $numitems = $this->getStatus('items');
118
+
119
+ foreach($chunks as $chunknum => $objItems)
120
+ {
121
+ $numitems += $this->DataProvider->enqueue($objItems);
122
+
123
+ //$last_id = $objItems[count($objItems)-1]->item_id;
124
+ $last_id = end($objItems)->item_id;
125
+
126
+ //var_dump(end($objItems)); var_dump($last_id);
127
+ $this->setStatus('last_item_id', $last_id); // save this, as a script termination safeguard.
128
+ }
129
+
130
+ $this->items = array(); // empty the item cache after inserting
131
+ $this->setStatus('items', $numitems, false);
132
+ $this->saveStatus();
133
+ return $numitems;
134
+ }
135
+
136
+ /** Accepts array of items with a certain priority
137
+ * Usage: $queue->withOrder($items, $order)->enqueue(); will add items with a specific list order number
138
+ * @param $items Items Array, see AddItems
139
+ * @param $order Int List Order number to insert.
140
+ * @return $Queue This Queue Object
141
+ */
142
+ public function withOrder($items, $order)
143
+ {
144
+ foreach($items as $index => $item)
145
+ {
146
+ $item['order'] = $order;
147
+ $items[$index] = $item;
148
+ }
149
+ $this->addItems($items);
150
+ return $this;
151
+ }
152
+
153
+ /* Remove from Queue possible duplicates
154
+ * Chained function. Removed items from queue
155
+ * *Note* This should be used with small selections of items, not by default. Only when changes to item are needed, or to status.
156
+ */
157
+ public function withRemoveDuplicates()
158
+ {
159
+
160
+ $item_ids = array();
161
+
162
+ foreach($this->items as $item)
163
+ {
164
+ $item_ids[] = $item->item_id;
165
+ }
166
+
167
+ $count = $this->DataProvider->removeRecords(array('items' => $item_ids));
168
+
169
+ if ($count > 0)
170
+ $this->setStatusCount('items', -$count );
171
+
172
+ return $this;
173
+ }
174
+
175
+
176
+ // Dequeue a record, put it on done in queue.
177
+ public function dequeue()
178
+ {
179
+
180
+ if ($this->currentStatus()->get('items') <= 0)
181
+ {
182
+ $still_here = $this->checkQueue();
183
+ // @todo if there is queue todo, update items, and go.
184
+ if (! $still_here)
185
+ return false;
186
+ }
187
+
188
+ $newstatus = ($this->options->mode == 'wait') ? ShortQ::QSTATUS_INPROCESS : ShortQ::QSTATUS_DONE;
189
+
190
+ $args = array(
191
+ 'numitems' => $this->options->numitems,
192
+ 'newstatus' => $newstatus,
193
+ );
194
+
195
+ $items = $this->DataProvider->dequeue($args);
196
+
197
+ $itemcount = count($items);
198
+
199
+ // @todo Ask dprovder for dequeue
200
+ // Update item count, average ask, last_run for this process
201
+ // When Q is empty, reask for item count for DataProvider and check if it the same, if not, update number, continue.
202
+ $items_left = $this->getStatus('items') - $itemcount;
203
+ $this->setStatus('items', $items_left , false);
204
+
205
+ if ($newstatus == self::QSTATUS_DONE)
206
+ $this->setStatusCount('done', $itemcount, false);
207
+ elseif($newstatus == self::QSTATUS_INPROCESS)
208
+ $this->setStatusCount('in_process', $itemcount, false);
209
+
210
+ $this->current_ask += $itemcount;
211
+
212
+ //$queue['average_ask'] = $this->calcAverageAsk($queue['average_ask']);
213
+ //$this->updateQueue($queue);
214
+ $this->setStatus('last_run', time(), false);
215
+ $this->setStatus('running', true, false);
216
+ $this->saveStatus();
217
+
218
+ if ($items_left == 0)
219
+ $this->checkQueue(); // possible need to end it.
220
+
221
+ return $items;
222
+ }
223
+
224
+ public function itemDone(Item $item)
225
+ {
226
+ if ($this->options->mode == 'direct')
227
+ {
228
+ $this->setStatusCount('items', -1, false);
229
+ }
230
+ elseif ($this->options->mode == 'wait')
231
+ {
232
+ $this->setStatusCount('in_process',-1, false);
233
+ }
234
+ else // no mode, no count, no nothing, mumble.
235
+ {
236
+ return false;
237
+ }
238
+
239
+ $this->setStatusCount('done', 1, false);
240
+
241
+ $this->saveStatus();
242
+
243
+ $this->DataProvider->itemUpdate($item, array('status' => ShortQ::QSTATUS_DONE));
244
+ }
245
+
246
+ public function itemFailed(Item $item, $fatal = false)
247
+ {
248
+ $status = ShortQ::QSTATUS_ERROR;
249
+ if ($fatal)
250
+ {
251
+ $status = ShortQ::QSTATUS_FATAL;
252
+ $this->setStatusCount('fatal_errors', 1 );
253
+ }
254
+ else
255
+ $this->setStatusCount('errors', 1 );
256
+
257
+ $item->tries++;
258
+ $this->DataProvider->itemUpdate($item, array('status' => $status, 'tries' => $item->tries));
259
+
260
+ }
261
+
262
+ public function hasItems()
263
+ {
264
+ //$status = $this->getQueueStatus();
265
+ $items = $this->itemCount(); // $status->get('items');
266
+ if ($items > 0)
267
+ return true;
268
+ else {
269
+ return false;
270
+ }
271
+ }
272
+
273
+ public function itemCount()
274
+ {
275
+ // $queue = $this->getQueueStatus();
276
+ $num = $this->getStatus('items'); //$queue->items;
277
+ if ($num <= 0)
278
+ {
279
+ $this->checkQueue(); // check and update left records before checking on Dprovider.
280
+ $num = $this->DataProvider->itemCount();
281
+ $this->setStatus('items', $num);
282
+ }
283
+ return $num;
284
+ }
285
+
286
+ /** Function to call when ending a queue process. The purpose is to purge all records and statistics.
287
+ * Those need to be collected before calling this function. Also the reason this is not done automatically.
288
+ */
289
+ public function resetQueue()
290
+ {
291
+ $this->DataProvider->removeRecords(array('all' => true));
292
+ $this->status['queues'][$this->qName] = new Status();
293
+ $this->saveStatus();
294
+ }
295
+
296
+ /** @todo Users must be able to control preparing / running status controls for resume / play the queue, but possibly not the counts. */
297
+ public function setStatus($name, $value, $savenow = true)
298
+ {
299
+ $r = $this->currentStatus()->set($name, $value);
300
+ $this->currentStatus()->set('last_update', time());
301
+
302
+ if (! $r)
303
+ return false;
304
+
305
+ if ($savenow)
306
+ $this->saveStatus(); // for now.
307
+
308
+ return true;
309
+ }
310
+
311
+ /** Addition of substraction for the counters */
312
+ public function setStatusCount($name, $change, $savenow = true)
313
+ {
314
+ if (! $this->currentStatus()->isCounter($name))
315
+ {
316
+ return false;
317
+ }
318
+
319
+ $count = $this->getStatus($name);
320
+ return $this->setStatus($name, $count + $change, $savenow);
321
+ }
322
+
323
+
324
+ /** Creates a Queue Data Array to keep
325
+ * This is intended as a run-once affair. Last Run, Average Ask should be kept.
326
+ *
327
+ */
328
+ private function createStatus()
329
+ {
330
+ $queue_status = new Status(); // this is a per-q status
331
+
332
+ if (! isset($this->status))
333
+ $this->status = array('queues');
334
+
335
+ $this->createQueue();
336
+
337
+ $this->DataProvider->install();
338
+
339
+ }
340
+
341
+ /** Get the current status of this slug / queue */
342
+ protected function currentStatus()
343
+ {
344
+ return $this->status['queues'][$this->qName];
345
+ }
346
+
347
+ private function createQueue()
348
+ {
349
+ if (! isset($this->status['queues'][$this->qName]))
350
+ {
351
+ $this->status['queues'][$this->qName] = new Status();
352
+ // $this->currentStatus = $this->status[$this->pSlug]['queues'][$this->qName];
353
+ $this->saveStatus();
354
+ }
355
+ }
356
+
357
+ private function loadStatus()
358
+ {
359
+ $this->status = get_option($this->statusName);
360
+
361
+ if (! $this->status || ! is_object($this->status))
362
+ $this->createStatus();
363
+
364
+
365
+ if (! isset($this->status['queues'][$this->qName]))
366
+ $this->createQueue();
367
+
368
+ // $this->currentStatus = $this->status[$this->pSlug]['queues'][$this->qName];
369
+ }
370
+
371
+ public function getStatus($item = false)
372
+ {
373
+ if (! $item)
374
+ return $this->currentStatus();
375
+ else
376
+ return $this->currentStatus()->get($item);
377
+ }
378
+
379
+ protected function saveStatus()
380
+ {
381
+ // $this->status[$this->pSlug]['queues'][$this->qName] = $this->currentStatus;
382
+ $status = get_option($this->statusName); // two different Q's can run simulanously.
383
+ $status['queues'][$this->qName] = $this->currentStatus();
384
+ update_option($this->statusName, $status);
385
+ }
386
+
387
+ /** Check Queue. This function intends to keep internal counts consistent with dataprovider without doing queries every run .
388
+ * Should also be able to spot the moment when there is nothing waiting, but perhaps some tasks as in process with a timeout. (stale)
389
+ */
390
+ private function checkQueue()
391
+ {
392
+ $this->resetInternalCounts(); // retrieve accurate count from dataSource.
393
+ // var_dump($this->currentStatus);
394
+
395
+ $tasks_done = $this->getStatus('done');
396
+ $tasks_open = $this->getStatus('items');
397
+ $tasks_inprocess = $this->getStatus('in_process');
398
+ $tasks_error = $this->getStatus('errors');
399
+
400
+ $mode = $this->options->mode;
401
+ $update_at_end = false;
402
+
403
+ if ($tasks_error > 0)
404
+ {
405
+ $update_at_end = true;
406
+ $error_args = array(
407
+ 'numitems' => $tasks_error,
408
+ 'status' => ShortQ::QSTATUS_ERROR,
409
+ // 'status' => ShortQ::QSTATUS_ERROR,
410
+ );
411
+
412
+ $error_items = $this->DataProvider->dequeue($error_args);
413
+ $retry_array = array();
414
+ $failed_array = array();
415
+ foreach($error_items as $errItem)
416
+ {
417
+ $errid = $errItem->item_id;
418
+ if ($errItem->tries < $this->options->retry_limit)
419
+ {
420
+ //$retry_array = $erritem->id;
421
+ $this->DataProvider->itemUpdate($errItem, array('status' => ShortQ::QSTATUS_WAITING));
422
+ }
423
+ else {
424
+ //$item = Item::import($erroritem->value);
425
+ //if ($item)
426
+ // {
427
+ // $item->errorCode = self::QSTATUS_FATAL;
428
+ // $item->errorMessage = 'WPQ - Number of retries surpassed settings';
429
+ $this->DataProvider->itemUpdate($errItem, array('status' => ShortQ::QSTATUS_FATAL));
430
+ // }
431
+ }
432
+ }
433
+ } // tasks_errors
434
+
435
+ if($update_at_end)
436
+ {
437
+ $this->resetInternalCounts(); // retrieve accurate count from dataSource.
438
+ //$status = $this->getQueueStatus();
439
+ $tasks_open = $this->currentStatus()->get('items');
440
+ $tasks_inprocess = $this->currentStatus()->get('in_process');
441
+ }
442
+
443
+ // $this->saveStatus(); // save result to DB.
444
+
445
+ if ($tasks_open > 0)
446
+ return true;
447
+ else {
448
+ $this->finishQueue();
449
+ return false;
450
+ }
451
+
452
+ return null;
453
+ }
454
+
455
+ private function resetInternalCounts()
456
+ {
457
+ $dataQ = $this->DataProvider->itemCount('countbystatus');
458
+ $num_items = $num_done = $num_in_process = $num_errors = $num_fatal = 0;
459
+
460
+ foreach($dataQ as $qstatus => $count)
461
+ {
462
+
463
+ switch($qstatus)
464
+ {
465
+ case ShortQ::QSTATUS_WAITING:
466
+ $num_items = $count;
467
+ break;
468
+ case ShortQ::QSTATUS_DONE:
469
+ $num_done = $count;
470
+ break;
471
+ case ShortQ::QSTATUS_INPROCESS:
472
+ $num_in_process = $count;
473
+ break;
474
+ case ShortQ::QSTATUS_ERROR:
475
+ $num_errors = $count;
476
+ break;
477
+ case ShortQ::QSTATUS_FATAL;
478
+ $num_fatal = $count;
479
+ break;
480
+ }
481
+ }
482
+
483
+
484
+ $this->setStatus('items', $num_items, false);
485
+ $this->setStatus('done', $num_done, false);
486
+ $this->setStatus('in_process', $num_in_process, false);
487
+ $this->setStatus('errors', $num_errors, false);
488
+ $this->setStatus('fatal_errors', $num_fatal, false);
489
+
490
+ $this->saveStatus();
491
+ // direct, to prevent loop.
492
+
493
+ }
494
+
495
+ private function calcAverageAsk($avg)
496
+ {
497
+ // @todo this is nonsense. Need a counter for X times run.
498
+ return ($avg / $this->current_ask);
499
+ }
500
+
501
+ private function finishQueue()
502
+ {
503
+ $this->setStatus('running', false, false);
504
+ $this->setStatus('finished', true, false);
505
+ $this->setStatus('last_run', time(), false);
506
+ $this->setStatusCount('times_ran', 1, false );
507
+ $this->saveStatus();
508
+
509
+ //@todo find some function to remove records, maybe check if all are either DONE OR FATAL
510
+ /*
511
+ Not true, if done are removed on queue finish it might impede getting stats from them. Since CheckQueue invokes both finishQueue and resetInternalCounter, removing from DB can end up with a 0 count, because the boss script is aware the queue is already empty.
512
+ if ($this->options->mode == 'direct') // only direct should be removed straight.
513
+ {
514
+ $args = array('status' => QSTATUS_DONE);
515
+ $this->DataProvider->removeRecords($args);
516
+ } */
517
+
518
+ //@todo find some way to report back what happened recently.
519
+ }
520
+
521
+
522
+ /** Function to call when uninstalling the plugin. This will remove only this current queue
523
+ */
524
+ public function unInstall()
525
+ {
526
+ // Remove the Queued Items
527
+
528
+ // @todo this will only remove the records of current queue, probably not good for uninstall
529
+ $this->DataProvider->removeRecords(array('all' => true));
530
+
531
+ // Unset the WP Option queue
532
+ //unset($this->status
533
+ unset($this->status['queues'][$this->qName]);
534
+
535
+ if (count($this->status['queues']) == 0)
536
+ delete_option($this->statusName);
537
+ else
538
+ $this->saveStatus();
539
+
540
+
541
+ // Signal to DataProvider to check if the whole thing can be removed. Won't happen when there are still records.
542
+ $this->DataProvider->uninstall();
543
+ }
544
+
545
+ }
build/shortpixel/shortq/src/ShortQ.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace ReThumbAdvanced\ShortQ;
3
+ //use \ReThumbAdvanced\ShortQ\Queue;
4
+ //use \ReThumbAdvanced\ShortQ\DataProvider;
5
+
6
+ // init
7
+ class ShortQ
8
+ {
9
+
10
+ const QSTATUS_ALL = -1; // special status, for query use
11
+ const QSTATUS_WAITING = 0;
12
+ const QSTATUS_PULLED = 1; // not in use atm.
13
+ const QSTATUS_INPROCESS = 2;
14
+ const QSTATUS_DONE = 3;
15
+
16
+ const QSTATUS_DELETE = -1; // this is a virtual status. If set to this, will be deleted.
17
+ const QSTATUS_ERROR = -2;
18
+ const QSTATUS_FATAL = -3;
19
+
20
+ protected $pluginSlug; // unique plugin name using Q.
21
+ protected $queueName;
22
+
23
+ protected static $queues = array();
24
+
25
+ public function __construct($pluginSlug)
26
+ {
27
+
28
+ $this->pluginSlug = $pluginSlug;
29
+ //self::$queues[$qname] = $this;
30
+ }
31
+
32
+ public function getQueue($qName, $lock = false)
33
+ {
34
+ // @todo get config from main parent file, or so.
35
+ $this->queue = 'wp';
36
+ $this->dataProvider = 'mysql';
37
+ $this->queueName = $qName;
38
+
39
+ // if nothing, then create a new Q.
40
+ $q = $this->QLoader();
41
+ return $q;
42
+ }
43
+
44
+ protected function QLoader()
45
+ {
46
+ $dataProvider = null;
47
+ switch($this->dataProvider)
48
+ {
49
+ case 'mysql':
50
+ $dataProvider = new DataProvider\MysqlDataProvider($this->pluginSlug, $this->queueName);
51
+ break;
52
+ }
53
+
54
+ switch($this->queue)
55
+ {
56
+ case 'wp':
57
+ default:
58
+ $newQ = new Queue\WPQ($this->pluginSlug, $this->queueName, $dataProvider);
59
+ break;
60
+ }
61
+
62
+ /* if (defined('SHORTPIXEL_DEBUG') && SHORTPIXEL_DEBUG)
63
+ {
64
+ $test = new Tests\Tests($newQ);
65
+ } */
66
+
67
+ self::$queues[$this->queueName] = $this;
68
+ return $newQ;
69
+ }
70
+
71
+ }
build/shortpixel/shortq/src/Status.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace ReThumbAdvanced\ShortQ;
3
+
4
+ /* Status Object to hold all relevant values for Queue Status like counts, times run etc.
5
+ * Provider-agnostic so doesn't mingle in saving / loading .
6
+ */
7
+
8
+ class Status
9
+ {
10
+
11
+ // Protecting against direct writing so at later point we can still add quality checks on setters.
12
+ protected $items = 0; // number of items waiting.
13
+ protected $in_process = 0; // amount of items currently in process ..
14
+ protected $preparing = false; // flag to signal queue is being created and items are being uploaded. Don't run.
15
+ protected $running = false; // flag to signal the queue is currently running
16
+ protected $finished = false; // flag to signal nothing can move this queue anymore.
17
+ protected $done = 0; // number of items processed
18
+ protected $errors = 0;
19
+ protected $fatal_errors = 0;
20
+ protected $last_run = 0; // internal
21
+ protected $last_update = 0; // internal
22
+ protected $times_ran = 0; // internal
23
+ protected $average_ask = 0; // internal
24
+
25
+ protected $last_item_id = 0;
26
+
27
+ public function isCounter($name)
28
+ {
29
+ if ( gettype($this->$name) == 'integer')
30
+ return true;
31
+ else
32
+ return false;
33
+ }
34
+
35
+ public function get($name)
36
+ {
37
+ if (isset($this->$name))
38
+ return $this->$name;
39
+ else
40
+ return null;
41
+ }
42
+
43
+ public function set($name, $value)
44
+ {
45
+ if(property_exists($this,$name))
46
+ {
47
+ if ($this->isCounter($name))
48
+ $value = intval($value);
49
+
50
+ $this->$name = $value;
51
+ return true;
52
+ }
53
+ return false;
54
+ }
55
+
56
+
57
+ }
build/shortpixel/shortq/src/Tests/Tests.php ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace ReThumbAdvanced\ShortQ\Tests;
3
+
4
+ class Tests{
5
+
6
+ protected $items = array();
7
+ // protected $text_items = array('test1','test2','test3','test4','test5','test6','test7');
8
+
9
+ protected $q;
10
+
11
+ public function __construct($q)
12
+ {
13
+ global $wpdb;
14
+ $wpdb->show_errors();
15
+ $this->startView();
16
+
17
+ $q->setOptions(array('is_debug' => true));
18
+
19
+ echo "<PRE> START STATUS "; print_r($q->getStatus()); echo "</PRE>";
20
+
21
+ for ($i = 0; $i < 10; $i++)
22
+ {
23
+ $id = rand(0, 1000);
24
+ $this->items[] = array('id' => $id, 'value' => $id);
25
+ }
26
+
27
+ $deq_number = rand(1, 5);
28
+ $q->setOption('numitems', $deq_number);
29
+
30
+ $this->q = $q;
31
+ // $this->uninstall();
32
+
33
+ if ( $this->q->hasItems())
34
+ {
35
+ echo "ITEMS FOUND: " . $this->q->itemCount() . "<BR>";
36
+ $this->runTestQ();
37
+ }
38
+ else {
39
+ $this->addItems();
40
+ $this->runTestQ();
41
+ // $this->addItems();
42
+ }
43
+
44
+ $this->results();
45
+
46
+ echo "<PRE> END STATUS "; print_r($q->getStatus()); echo "</PRE>";
47
+ $this->endView();
48
+ }
49
+
50
+ public function addItems()
51
+ {
52
+ print_r($this->items);
53
+ $this->q->enqueue($this->items);
54
+ }
55
+
56
+ public function runTestQ()
57
+ {
58
+ $this->deQueueBasic();
59
+ }
60
+
61
+ public function deQueueBasic()
62
+ {
63
+ while($this->q->hasItems())
64
+ {
65
+ $item = $this->q->deQueue();
66
+ echo "ITEM FROM THA Q "; var_dump($item);
67
+ }
68
+ }
69
+
70
+ public function uninstall()
71
+ {
72
+ $this->q->uninstall();
73
+ }
74
+
75
+ //public function deQueu
76
+
77
+ public function results()
78
+ {
79
+ global $wpdb;
80
+ echo $wpdb->last_error;
81
+ }
82
+
83
+ public function startView()
84
+ {
85
+ ?>
86
+ <div class='debug' style='margin: 100px 0 100px 250px; background: #fff;'>
87
+ <?php
88
+ }
89
+
90
+ public function endView()
91
+ {
92
+ ?>
93
+ </div>
94
+ <?php
95
+ }
96
+
97
+ } // class
classes/Admin.php ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ *
10
+ * @category Admin Side Code
11
+ * @package Regenerate Thumbnails Advanced
12
+ * @author ShortPixel
13
+ */
14
+
15
+ class Admin
16
+ {
17
+ /*private $process_remove_thumbnails = false;
18
+ private $process_delete_leftmetadata = false;
19
+ private $process_cleanup_metadata = false;
20
+ */
21
+ private static $instance;
22
+
23
+ protected $custom_image_sizes = array();
24
+ protected $process_image_sizes = false;
25
+ protected $process_image_options = array();
26
+ protected $system_image_sizes = array();
27
+ protected $jpeg_quality = 90;
28
+
29
+ //Admin side starting point. Will call appropriate admin side hooks
30
+ public function __construct() {
31
+ $this->setOptionData();
32
+ }
33
+
34
+ public static function getInstance()
35
+ {
36
+ if (! isset(self::$instance))
37
+ {
38
+ self::$instance = new Admin();
39
+ }
40
+
41
+ return self::$instance;
42
+ }
43
+
44
+ protected function setOptionData()
45
+ {
46
+ $options = get_option('rta_image_sizes', $this->getDefaultOptions() );
47
+
48
+ if (isset($options['image_sizes']) && is_array($options['image_sizes']))
49
+ $this->custom_image_sizes = $options['image_sizes'];
50
+
51
+ if (isset($options['jpeg_quality']))
52
+ $this->jpeg_quality = $options['jpeg_quality'];
53
+
54
+ if (isset($options['process_image_sizes']) && is_array($options['process_image_sizes']))
55
+ $this->process_image_sizes = $options['process_image_sizes'];
56
+ else
57
+ $this->process_image_sizes = array();
58
+
59
+
60
+ if (isset($options['process_image_options']) && is_array($options['process_image_options']) )
61
+ $this->process_image_options = $options['process_image_options'];
62
+ else
63
+ $this->process_image_options = array();
64
+
65
+ $this->system_image_sizes = $this->getImageSizes();
66
+ }
67
+
68
+ /** Returns system wide defined image sizes plus our custom sizes
69
+ *
70
+ *
71
+ */
72
+ public function getImageSizes()
73
+ {
74
+ global $_wp_additional_image_sizes;
75
+
76
+ $option = get_option('rta_image_sizes');
77
+ $our_image_sizes = isset($option['image_sizes']) ? $option['image_sizes']: array();
78
+
79
+ $imageSizes = array();
80
+ foreach ( get_intermediate_image_sizes() as $_size )
81
+ {
82
+ if ( strpos($_size, 'rta_') === false)
83
+ $imageSizes[$_size] = $_size;
84
+ }
85
+
86
+ // put our defined images manually, to properly update when sizes /names change.
87
+ if (isset($our_image_sizes['pname']))
88
+ {
89
+ for($i = 0; $i < count($our_image_sizes['pname']); $i++ )
90
+ {
91
+ $int_name = $our_image_sizes['name'][$i];
92
+ $name = $our_image_sizes['pname'][$i];
93
+ if (strlen($name) == 0) // can't since name is tied to what it gives back to the process
94
+ $name = $int_name;
95
+
96
+ $imageSizes[$int_name] = $name;
97
+ }
98
+ }
99
+ return $imageSizes;
100
+
101
+ }
102
+
103
+ public function resetOptionData()
104
+ {
105
+ $this->setOptionData();
106
+ }
107
+
108
+ private function getDefaultOptions()
109
+ {
110
+ $standard_sizes = array( 'thumbnail', 'medium', 'medium_large', 'large' ); // directly from media.php, hardcoded there.
111
+ $process_image_options = array();
112
+ foreach($standard_sizes as $name)
113
+ {
114
+ $process_image_options[$name] = array('overwrite_files' => false);
115
+ }
116
+ $options = array();
117
+ $options['process_image_sizes'] = $standard_sizes;
118
+ $options['process_image_options'] = $process_image_options;
119
+
120
+ return $options;
121
+ }
122
+
123
+ public function getOption($name)
124
+ {
125
+ if (isset($this->$name))
126
+ return $this->$name;
127
+
128
+ return false;
129
+ }
130
+
131
+ public function regenerate_single_image($attach_id)
132
+ {
133
+ /* $form = $this->getFormData();
134
+ $form['posts_per_page'] = -1;
135
+ $form['attach_id'] = $attach_id;
136
+ */
137
+ $image = new Image($attach_id);
138
+ $image->regenerate();
139
+
140
+ /*if ($this->start_process($form))
141
+ {
142
+ $this->regenerate_thumbnails();
143
+ }
144
+ */
145
+ $status = RTA()->ajax()->get_status();
146
+
147
+ foreach($status as $statusName => $statusItem)
148
+ {
149
+ if ($statusItem['error'])
150
+ Notice::addError($statusItem['message']);
151
+ elseif ($statusItem['status'] == 1)
152
+ Notice::addSuccess(__('Image thumbnails regenerated', 'regenerate-thumbnails-advanced'));
153
+ else
154
+ Notice::addNormal($statusItem['message']);
155
+ }
156
+
157
+ // $this->end_process();
158
+ }
159
+
160
+ } // Class
classes/AjaxController.php ADDED
@@ -0,0 +1,352 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace ReThumbAdvanced;
3
+ use \ReThumbAdvanced\ShortPixelLogger\ShortPixelLogger as Log;
4
+ use \ReThumbAdvanced\Controllers\AdminController as AdminController;
5
+
6
+ // For communication with the Javascripting.
7
+ class AjaxController
8
+ {
9
+ protected static $instance;
10
+ protected $status; // /for the status.s
11
+
12
+ // Ok status
13
+ const STATUS_OK = 0;
14
+ const STATUS_SUCCESS = 1;
15
+ const STATUS_STOPPED = 10;
16
+ const STATUS_FINISHED = 11;
17
+
18
+ // Errors
19
+ const ERROR_GENERAL = -1;
20
+ const ERROR_NOFILE = -2;
21
+ const ERROR_METADATA = -3;
22
+
23
+ /** PERIOD OPTIONS */
24
+ const PERIOD_ALL = 0;
25
+ const PERIOD_DAY = 1;
26
+ const PERIOD_WEEK = 2;
27
+ const PERIOD_MONTH = 3;
28
+ const PERIOD_3MONTH = 4;
29
+ const PERIOD_6MONTH = 5;
30
+ const PERIOD_YEAR = 6;
31
+
32
+ public static function getInstance()
33
+ {
34
+ if (is_null(self::$instance))
35
+ {
36
+ self::$instance = new ajaxController();
37
+ }
38
+
39
+ return self::$instance;
40
+ }
41
+
42
+ // hooks
43
+ public function init()
44
+ {
45
+ // Process JS
46
+ add_action( 'wp_ajax_rta_do_process', array($this, 'ajax_do_process') );
47
+ add_action( 'wp_ajax_rta_start_process', array($this, 'ajax_start_process') );
48
+ add_action( 'wp_ajax_rta_stop_process', array($this, 'ajax_stop_process'));
49
+
50
+ // For settings page
51
+ add_action( 'wp_ajax_rta_save_image_sizes', array($this,'view_generate_thumbnails_save' ) );
52
+
53
+ }
54
+
55
+ public function add_status($name, $args = array() )
56
+ {
57
+ $status = array('error' => true, 'message' => __('Unknown Error occured', 'regenerate-thumbnails-advanced'), 'status' => 0);
58
+
59
+ $defaults = array(
60
+ 'name' => false,
61
+ 'thumb' => false,
62
+ 'count' => false,
63
+ );
64
+
65
+ $args = wp_parse_args($args, $defaults);
66
+
67
+ switch($name)
68
+ {
69
+ case 'no_nonce':
70
+ $status['message'] = __('Site error, Invalid Nonce', 'regenerate-thumbnails-advanced');
71
+ $status['status'] = self::ERROR_GENERAL;
72
+ break;
73
+ case 'preparing':
74
+ $status['message'] = __('Preparing Images and Thumbnails', 'regenerate-thumbnails-advanced');
75
+ $status['status'] = self::STATUS_OK;
76
+ $status['error'] = false;
77
+ break;
78
+ case 'prepared':
79
+ $status['message'] = __('Prepared %s items', 'regenerate-thumbnails-advanced');
80
+ $status['mask'] = array('count');
81
+ $status['status'] = self::STATUS_OK;
82
+ $status['error'] = false;
83
+ break;
84
+ case 'prepare_failed':
85
+ $status['message'] = __('Preparing failed', 'regenerate-thumbnails-advanced');
86
+ $status['status'] = self::ERROR_GENERAL;
87
+ break;
88
+ case 'no_images':
89
+ $status['message'] = __('No images found for this period and/or settings or none uploaded', 'regenerate-thumbnails-advanced');
90
+ $status['status'] = self::STATUS_OK;
91
+ $status['error'] = false;
92
+ break;
93
+ case 'file_missing':
94
+ $status['message'] = __('<b>%s</b> is missing or not an image file', 'regenerate-thumbnails-advanced');
95
+ $status['mask'] = array('name');
96
+ $status['status'] = self::ERROR_NOFILE;
97
+ break;
98
+ case 'not_image':
99
+ $status['message'] = __('<b>%s</b> skipped. MimeType is an image, but reports non-displayable', 'regenerate-thumbnails-advanced');
100
+ $status['mask'] = array('name');
101
+ $status['status'] = self::ERROR_NOFILE;
102
+ break;
103
+ case 'error_metadata':
104
+ $status['message'] = __('<b>%s</b> failed on metadata. Possible issue with image', 'regenerate-thumbnails-advanced');
105
+ $status['mask'] = array('name');
106
+ $status['status'] = self::ERROR_METADATA;
107
+ break;
108
+ case 'request_stop':
109
+ $status['message'] = __('Process stopped on request', 'regenerate-thumbnails-advanced');
110
+ $status['status'] = self::STATUS_STOPPED;
111
+ break;
112
+ case 'regenerate_success':
113
+ $status['message'] = '%s';
114
+ $status['mask'] = array('thumb');
115
+ $status['status'] = self::STATUS_SUCCESS;
116
+ $status['error'] = false;
117
+ break;
118
+
119
+ default:
120
+ $status['message'] = '[' . $name . ']';
121
+
122
+ break;
123
+ }
124
+
125
+ if (isset($status['mask']))
126
+ {
127
+ $mask = $status['mask'];
128
+ foreach($mask as $mname)
129
+ {
130
+ if ( isset($args[$mname]) )
131
+ {
132
+ $value = $args[$mname];
133
+ $pos = strpos($status['message'], '%s');
134
+
135
+ if ($pos !== false) {
136
+ $status['message'] = substr_replace($status['message'], $value, $pos, strlen('%s'));
137
+ }
138
+ }
139
+ }
140
+ }
141
+
142
+ if (isset($status['mask']))
143
+ unset($status['mask']); // internal use.
144
+
145
+ $this->status[] = $status;
146
+ }
147
+
148
+ public function get_status()
149
+ {
150
+ return $this->status;
151
+ }
152
+
153
+ public function ajax_start_process()
154
+ {
155
+
156
+ $this->checkNonce('rta_generate');
157
+
158
+ if (isset($_POST['genform']))
159
+ {
160
+ $form = $this->getFormData();
161
+ $process = RTA()->process();
162
+
163
+ $process->setRemoveThumbnails($form['del_associated_thumbs']);
164
+ $process->setDeleteLeftMeta($form['del_leftover_metadata']);
165
+ $process->setCleanMetadata($form['process_clean_metadata']);
166
+ $process->setOnlyFeatured($form['regenonly_featured']);
167
+
168
+ $stamps = $this->getQueryDate($form['period']);
169
+ // if ($period['date'] !== false)
170
+ //{
171
+ $startstamp = $stamps['startstamp']; // $period['args']['startstamp'];
172
+ $endstamp = $stamps['endstamp']; // period['args']['endstamp'];
173
+ $process->setTime($startstamp, $endstamp);
174
+ //}
175
+
176
+ $this->add_status('preparing');
177
+ $process->start();
178
+ $result = $this->runprocess(); // This would mostly be preparing.
179
+ }
180
+ else {
181
+ Log::addError('Ajax Start Process - Starting without form post');
182
+ exit(0);
183
+ }
184
+
185
+ //wp_send_json($this->get_json_process());
186
+ }
187
+
188
+ /** Collect form data, make a storable process array out of it */
189
+ protected function getFormData()
190
+ {
191
+ $defaults = array(
192
+ //'period' => self::PERIOD_ALL,
193
+ 'regenonly_featured' => false,
194
+ 'del_associated_thumbs' => false,
195
+ 'del_leftover_metadata' => false,
196
+ 'process_clean_metadata' => false,
197
+ );
198
+
199
+ $data = array();
200
+ $form = isset($_POST['genform']) ? $_POST['genform'] : '';
201
+ parse_str($form, $data);
202
+
203
+ return wp_parse_args($data, $defaults);
204
+ }
205
+
206
+ // retrieve JS friendly overview, if we are in process and if yes, what are we doing here.
207
+ public function get_json_process()
208
+ {
209
+ //$json = array('running' => false);
210
+ $process = RTA()->process();
211
+ $json = array();
212
+ $json['running'] = $process->get('running');
213
+ $json['preparing'] = $process->get('preparing');
214
+ $json['finished'] = $process->get('finished');
215
+ $json['done'] = $process->get('done');
216
+ $json['items'] = $process->get('items');
217
+ $json['errors'] = $process->get('errors');
218
+ $json['status'] = $this->status;
219
+ return $json;
220
+ }
221
+
222
+ public function ajax_do_process()
223
+ {
224
+ $this->checkNonce('rta_do_process');
225
+
226
+ $result = $this->runProcess();
227
+ $this->jsonResponse($this->get_json_process());
228
+ exit();
229
+ }
230
+
231
+ protected function runProcess()
232
+ {
233
+ // check if preparing, or running
234
+ $process = RTA()->process();
235
+ if ($process->get('preparing') == true) // prepare loop
236
+ {
237
+ $count = $process->prepare();
238
+ $this->add_status('prepared', array('count' => $count));
239
+ $this->jsonResponse($this->get_json_process());
240
+ }
241
+
242
+ if ($process->get('running') == true)
243
+ {
244
+ $items = $process->getItems();
245
+
246
+ if ($items)
247
+ {
248
+ foreach($items as $item)
249
+ {
250
+ $item_id = $item->item_id;
251
+ $image = new Image($item_id);
252
+ $status = $image->regenerate();
253
+ }
254
+ }
255
+ }
256
+
257
+
258
+ if ($process->get('finished') == true)
259
+ {
260
+ if ($process->get('done') == 0) // if Q is finished with 0 done, it was empty.
261
+ $this->add_status('no_images');
262
+
263
+ $this->jsonResponse($this->get_json_process());
264
+ }
265
+ }
266
+
267
+ public function ajax_stop_process()
268
+ {
269
+ $this->checkNonce('rta_generate');
270
+
271
+ // $this->process = $this->get_json_process();
272
+ $process = RTA()->process();
273
+ $process->end();
274
+ $this->add_status('request_stop');
275
+
276
+ $this->jsonResponse($this->get_json_process());
277
+ }
278
+
279
+ /* Saves and generates JSON response */
280
+ public function view_generate_thumbnails_save()
281
+ {
282
+ $json = true;
283
+ $view = new AdminController($this);
284
+ $response = $view->save_image_sizes();
285
+
286
+ if ($json)
287
+ {
288
+ $this->jsonResponse($response);
289
+ }
290
+ else
291
+ {
292
+ return $response;
293
+ }
294
+ }
295
+
296
+ // period comes from form.
297
+ protected function getQueryDate($period)
298
+ {
299
+ $now = time();
300
+ $endstamp = $now;
301
+ switch (intval($period)) {
302
+ case self::PERIOD_ALL:
303
+ $startstamp = 0;
304
+ break;
305
+ case self::PERIOD_DAY:
306
+ $startstamp = $now - DAY_IN_SECONDS;
307
+ break;
308
+ case self::PERIOD_WEEK:
309
+ $startstamp = $now - WEEK_IN_SECONDS;
310
+ break;
311
+ case self::PERIOD_MONTH:
312
+ $startstamp = $now - MONTH_IN_SECONDS;
313
+ break;
314
+ case self::PERIOD_3MONTH:
315
+ $startstamp = $now - (3* MONTH_IN_SECONDS);
316
+ break;
317
+ case self::PERIOD_6MONTH:
318
+ $startstamp = $now - (6* MONTH_IN_SECONDS);
319
+ break;
320
+ case self::PERIOD_YEAR:
321
+ $startstamp = $now - YEAR_IN_SECONDS;
322
+ break;
323
+ }
324
+ // $result = array('date' => $date, 'args' => $args);
325
+ $result = array('startstamp' => $startstamp, 'endstamp' => $endstamp);
326
+ return $result;
327
+ }
328
+
329
+ // No Noncense function.
330
+ protected function checkNonce($action)
331
+ {
332
+ $nonce = isset($_POST['nonce']) ? $_POST['nonce'] : false;
333
+
334
+ if (! wp_verify_nonce($nonce, $action))
335
+ {
336
+ $this->add_status('no_nonce');
337
+ Log::addError('Ajax Start Process - Nonce failed ' . $nonce . 'on ' . $action);
338
+ $this->jsonResponse($this->get_json_process());
339
+ exit();
340
+ }
341
+
342
+ return true;
343
+ }
344
+
345
+ /** Central function for JSON responses. Can be extended whenever needed */
346
+ protected function jsonResponse($response)
347
+ {
348
+ wp_send_json($response);
349
+ exit();
350
+ }
351
+
352
+ }
classes/{rta_admin_controller.php → Controllers/AdminController.php} RENAMED
@@ -1,22 +1,26 @@
1
  <?php
 
 
2
 
3
- class rtaAdminController
4
  {
5
- protected $controller;
6
 
7
  /** Settings saved in the option table. Being set on construct. Refreshed on save */
8
- protected $custom_image_sizes = array();
9
  protected $process_image_sizes = false;
10
  protected $process_image_options = array();
11
- protected $jpeg_quality = 90;
 
12
 
13
  protected $cropOptions;
14
 
15
- public function __construct($controller)
16
  {
17
- wp_enqueue_style( 'rta_css_admin', RTA_PLUGIN_URL.'css/rta-admin-view.css', array(), RTA_PLUGIN_VERSION );
 
18
 
19
- $this->controller = $controller;
20
 
21
  $this->cropOptions = array(
22
  'no_cropped' => __('No','regenerate-thumbnails-advanced'),
@@ -32,41 +36,32 @@ class rtaAdminController
32
  'right_bottom' => __('Right bottom','regenerate-thumbnails-advanced'),
33
  );
34
 
35
- $this->setOptionData();
36
 
37
  }
38
 
39
- protected function setOptionData()
40
- {
41
- $options = get_option('rta_image_sizes');
42
- if (isset($options['image_sizes']) && is_array($options['image_sizes']))
43
- $this->custom_image_sizes = $options['image_sizes'];
44
-
45
- if (isset($options['jpeg_quality']))
46
- $this->jpeg_quality = $options['jpeg_quality'];
47
-
48
- if (isset($options['process_image_sizes']) && is_array($options['process_image_sizes']))
49
- $this->process_image_sizes = $options['process_image_sizes'];
50
- else
51
- $this->process_image_sizes = array();
52
-
53
 
54
- if (isset($options['process_image_options']) && is_array($options['process_image_options']) )
55
- $this->process_image_options = $options['process_image_options'];
56
- else
57
- $this->process_image_options = array();
58
-
59
- }
60
 
61
  public function show()
62
  {
63
- $html = $this->controller->rta_load_template( "rta_generate_thumbnails", "admin", array('view' => $this) );
 
 
64
  echo $html;
65
  }
66
 
67
  public function loadChildTemplate($name)
68
  {
69
- $html = $this->controller->rta_load_template($name, 'admin', array('view' => $this ));
 
 
 
 
 
 
 
 
 
70
  echo $html;
71
  }
72
 
@@ -85,6 +80,7 @@ class rtaAdminController
85
  return $output;
86
  }
87
 
 
88
  public function __get($name)
89
  {
90
  if (isset($this->{$name}))
@@ -92,7 +88,7 @@ class rtaAdminController
92
  return $this->{$name};
93
  }
94
  return false;
95
- }
96
 
97
  /** Save thumbnail settings.
98
  *
@@ -162,7 +158,8 @@ class rtaAdminController
162
  $option['process_image_options'] = $size_options;
163
 
164
  update_option( 'rta_image_sizes', $option );
165
- $this->setOptionData();
 
166
 
167
  $newsizes = $this->generateImageSizeOptions($sizes);
168
  $jsonResponse = array( 'error' => $error, 'message' => '', 'new_image_sizes' => $newsizes );
@@ -171,40 +168,6 @@ class rtaAdminController
171
 
172
  }
173
 
174
- /** Returns system wide defined image sizes plus our custom sizes
175
- *
176
- * This function is exclusively meant for display / view purposes
177
- */
178
- public function getImageSizes()
179
- {
180
- global $_wp_additional_image_sizes;
181
-
182
- $option = get_option('rta_image_sizes');
183
- $our_image_sizes = isset($option['image_sizes']) ? $option['image_sizes']: array();
184
-
185
- $imageSizes = array();
186
- foreach ( get_intermediate_image_sizes() as $_size )
187
- {
188
- if ( strpos($_size, 'rta_') === false)
189
- $imageSizes[$_size] = $_size;
190
- }
191
-
192
- // put our defined images manually, to properly update when sizes /names change.
193
- if (isset($our_image_sizes['pname']))
194
- {
195
- for($i = 0; $i < count($our_image_sizes['pname']); $i++ )
196
- {
197
- $int_name = $our_image_sizes['name'][$i];
198
- $name = $our_image_sizes['pname'][$i];
199
- if (strlen($name) == 0) // can't since name is tied to what it gives back to the process
200
- $name = $int_name;
201
-
202
- $imageSizes[$int_name] = $name;
203
- }
204
- }
205
- return $imageSizes;
206
-
207
- }
208
 
209
  public function generateImageSizeOptions($checked_ar = false)
210
  {
@@ -212,10 +175,13 @@ class rtaAdminController
212
  $i = 0;
213
  $check_all = ($checked_ar === false) ? true : false;
214
 
215
- $process_options = $this->process_image_options;
 
 
 
216
 
217
  // size here is a name, value is how the name is found in the system (in interface, the technical name)
218
- foreach($this->getImageSizes() as $value => $size):
219
 
220
  //if ($check_all)
221
  //$checked = 'checked';
@@ -233,10 +199,11 @@ class rtaAdminController
233
  <label> <input type='checkbox' id='regenerate_sizes[$i]' name='regenerate_sizes[$i]' value='$value' $checked>
234
  " . ucfirst($size) . "</label>
235
  </span>";
236
- $output .= "<span class='options $hidden'><label><input value='1' type='checkbox' $checked_keep name='keep_" . $value . "'> " . __('Keep existing', 'regenerate-thumbnails-advanced') . "</label></span>";
237
  $output .= "</div>";
238
 
239
  $i++;
 
240
  endforeach;
241
  return $output;
242
  }
1
  <?php
2
+ namespace ReThumbAdvanced\Controllers;
3
+ use function ReThumbAdvanced\RTA;
4
 
5
+ class AdminController extends Controller
6
  {
7
+ //protected $controller;
8
 
9
  /** Settings saved in the option table. Being set on construct. Refreshed on save */
10
+ /* protected $custom_image_sizes = array();
11
  protected $process_image_sizes = false;
12
  protected $process_image_options = array();
13
+ protected $system_image_sizes = array();
14
+ protected $jpeg_quality = 90; */
15
 
16
  protected $cropOptions;
17
 
18
+ public function __construct()
19
  {
20
+ wp_enqueue_style( 'rta_css_admin');
21
+ wp_enqueue_style( 'rta_css_admin_progress');
22
 
23
+ // $this->controller = $controller;
24
 
25
  $this->cropOptions = array(
26
  'no_cropped' => __('No','regenerate-thumbnails-advanced'),
36
  'right_bottom' => __('Right bottom','regenerate-thumbnails-advanced'),
37
  );
38
 
39
+ // $this->setOptionData();
40
 
41
  }
42
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
 
 
 
 
 
 
 
44
 
45
  public function show()
46
  {
47
+ $view = new \stdClass;
48
+
49
+ $html = $this->load_template( "rta_generate_thumbnails", "admin", array('view' => $view) );
50
  echo $html;
51
  }
52
 
53
  public function loadChildTemplate($name)
54
  {
55
+ $view = new \stdClass;
56
+ if ($name == 'view_rta_settings')
57
+ {
58
+ $view->custom_image_sizes = RTA()->admin()->getOption('custom_image_sizes');
59
+ $view->process_image_sizes = RTA()->admin()->getOption('process_image_sizes');
60
+ $view->process_image_options = RTA()->admin()->getOption('process_image_options');
61
+ $view->jpeg_quality = RTA()->admin()->getOption('jpeg_quality');
62
+ }
63
+
64
+ $html = $this->load_template($name, 'admin', array('view' => $view ));
65
  echo $html;
66
  }
67
 
80
  return $output;
81
  }
82
 
83
+ /*
84
  public function __get($name)
85
  {
86
  if (isset($this->{$name}))
88
  return $this->{$name};
89
  }
90
  return false;
91
+ } */
92
 
93
  /** Save thumbnail settings.
94
  *
158
  $option['process_image_options'] = $size_options;
159
 
160
  update_option( 'rta_image_sizes', $option );
161
+ //$this->setOptionData();
162
+ RTA()->admin()->resetOptionData();
163
 
164
  $newsizes = $this->generateImageSizeOptions($sizes);
165
  $jsonResponse = array( 'error' => $error, 'message' => '', 'new_image_sizes' => $newsizes );
168
 
169
  }
170
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
 
172
  public function generateImageSizeOptions($checked_ar = false)
173
  {
175
  $i = 0;
176
  $check_all = ($checked_ar === false) ? true : false;
177
 
178
+ //$process_options = $this->process_image_options;
179
+ $process_options = RTA()->admin()->getOption('process_image_options');
180
+
181
+ $system_image_sizes = RTA()->admin()->getOption('system_image_sizes');
182
 
183
  // size here is a name, value is how the name is found in the system (in interface, the technical name)
184
+ foreach($system_image_sizes as $value => $size):
185
 
186
  //if ($check_all)
187
  //$checked = 'checked';
199
  <label> <input type='checkbox' id='regenerate_sizes[$i]' name='regenerate_sizes[$i]' value='$value' $checked>
200
  " . ucfirst($size) . "</label>
201
  </span>";
202
+ $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>";
203
  $output .= "</div>";
204
 
205
  $i++;
206
+
207
  endforeach;
208
  return $output;
209
  }
classes/{rta_controller.php → Controllers/Controller.php} RENAMED
@@ -1,17 +1,10 @@
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
 
@@ -37,4 +30,9 @@ class rtaController
37
 
38
  return $html;
39
  }
 
 
 
 
 
40
  } // class
1
  <?php
2
+ namespace ReThumbAdvanced\Controllers;
 
3
 
4
  // Main Controller
5
+ class Controller
6
  {
7
 
 
 
 
 
 
 
8
  /** @todo not sur why this is such a complicated function */
9
  public function load_template( $template='', $for='front', $attr=array() ) {
10
 
30
 
31
  return $html;
32
  }
33
+
34
+ public function getURL($path)
35
+ {
36
+ return plugins_url($path, RTA_PLUGIN_FILE);
37
+ }
38
  } // class
classes/{rta_front.php → Front.php} RENAMED
@@ -14,7 +14,7 @@ namespace ReThumbAdvanced;
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() {
@@ -59,5 +59,5 @@ class RTA_Front
59
  return $new_sizes;
60
  }
61
 
62
-
63
  }
14
  * @since File available since Release 1.0.0
15
  */
16
 
17
+ class Front
18
  {
19
  //Front side starting point. Will call appropriate front side hooks
20
  public function __construct() {
59
  return $new_sizes;
60
  }
61
 
62
+
63
  }
classes/Image.php ADDED
@@ -0,0 +1,443 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace ReThumbAdvanced;
3
+ use \ReThumbAdvanced\ShortPixelLogger\ShortPixelLogger as Log;
4
+
5
+
6
+ class Image
7
+ {
8
+ protected $id;
9
+
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;
17
+ protected $fileDir;
18
+ protected $metadata = array();
19
+
20
+ protected $persistentMeta = array();
21
+ protected $regeneratedSizes = array();
22
+
23
+ protected $customThumbSuffixes = array('_c', '_tl', '_tr', '_br', '_bl');
24
+
25
+ public function __construct($image_id)
26
+ {
27
+ $this->id = $image_id;
28
+
29
+ if (function_exists('wp_get_original_image_path')) // WP 5.3+
30
+ {
31
+ $this->filePath = wp_get_original_image_path($image_id);
32
+ /** When this function returns false it's possible the post_mime_type in wp_posts table got corrupted. If the file is displayable image,
33
+ * attempt to fix this issue, then reget the item for further processing */
34
+ if ($this->filePath === false)
35
+ {
36
+ $this->filePath = get_attached_file($image_id);
37
+ if (file_is_displayable_image($this->filePath))
38
+ {
39
+ $this->fixMimeType($image_id);
40
+ $this->filePath = wp_get_original_image_path($image_id);
41
+ }
42
+ }
43
+ }
44
+ else
45
+ $this->filePath = get_attached_file($image_id);
46
+ $this->fileDir = trailingslashit(pathinfo($this->filePath, PATHINFO_DIRNAME));
47
+
48
+ if (function_exists('wp_get_original_image_url')) // WP 5.3+
49
+ $this->fileUri = wp_get_original_image_url($image_id);
50
+ else
51
+ $this->fileUri = wp_get_attachment_url($image_id);
52
+
53
+ if (!file_exists($this->filePath))
54
+ $this->does_exist = false;
55
+
56
+ if (! file_is_displayable_image($this->filePath)) // this is based on getimagesize
57
+ $this->is_image = false;
58
+
59
+ $this->metadata = wp_get_attachment_metadata($image_id);
60
+
61
+ /* $is_image_mime = wp_attachment_is('image', $image_id); // this is based on post mime.
62
+ if (! $is_image_mime && $this->is_image )
63
+ {
64
+ $this->fixMimeType($image_id);
65
+ }
66
+ */
67
+ }
68
+
69
+ public function regenerate()
70
+ {
71
+ if (RTA()->process()->doRemoveThumbnails())
72
+ {
73
+ $this->setCleanUp(true);
74
+ Log::addDebug('Image thumbnails will be cleaned');
75
+ }
76
+
77
+ if(RTA()->process()->doDeleteLeftMeta() && ! $this->exists() ) {
78
+
79
+ Log::addDebug('Deleting post ' . $this->id);
80
+ wp_delete_post($this->id, true);
81
+
82
+ }
83
+
84
+ if ($this->isImage() ) {
85
+
86
+ @set_time_limit(900);
87
+ do_action('shortpixel-thumbnails-before-regenerate', $this->id);
88
+
89
+ //use the original main image if exists
90
+ $backup = apply_filters('shortpixel_get_backup', $this->getPath() );
91
+ if($backup && $backup !== $this->filePath) {
92
+ Log::addDebug('Retrieving SPIO backups for process');
93
+ copy($this->getPath(), $backup . "_optimized_" . $this->id);
94
+ copy($backup, $this->getPath());
95
+ }
96
+
97
+ add_filter('intermediate_image_sizes_advanced', array($this, 'capture_generate_sizes'));
98
+ // RTA should never touch source files. This happens when redoing scaling. This would also be problematic in combination with optimisers. Disable scaling when doing thumbs.
99
+ add_filter('big_image_size_threshold', array($this, 'disable_scaling'));
100
+
101
+ $new_metadata = wp_generate_attachment_metadata($this->id, $this->filePath);
102
+
103
+ remove_filter('intermediate_image_sizes_advanced', array($this, 'capture_generate_sizes'));
104
+ remove_filter('big_image_size_threshold', array($this, 'disable_scaling'));
105
+
106
+ Log::addDebug('New Attachment metadata generated');
107
+ //restore the optimized main image
108
+ if($backup && $backup !== $this->filePath) {
109
+ rename($backup . "_optimized_" . $this->id, $this->filePath);
110
+ }
111
+
112
+ //get the attachment name
113
+ if (is_wp_error($new_metadata)) {
114
+
115
+ RTA()->ajax()->add_status('error_metadata', array('name' => basename($this->filePath) ));
116
+ }
117
+ else if (empty($new_metadata)) {
118
+ Log::addDebug('File missing - New metadata returned empty', array($new_metadata, $this->fileUri,$this->filePath ));
119
+ RTA()->ajax()->add_status('file_missing', array('name' => basename($this->fileUri) ));
120
+ } else {
121
+
122
+ // going for the save.
123
+ $original_meta = $this->getMetaData();
124
+ $result = $this->saveNewMeta($new_metadata); // this here calls the regeneration.
125
+ Log::addDebug('Result :', $result);
126
+
127
+ $is_a_bulk = true; // we are sending multiple images.
128
+ $regenSizes = isset($new_metadata['sizes']) ? $new_metadata['sizes'] : array();
129
+
130
+ // Do not send if nothing was regenerated, otherwise SP thinks all needs to be redone
131
+ if (count($regenSizes) > 0)
132
+ {
133
+ do_action('shortpixel-thumbnails-regenerated', $this->id, $original_meta, $regenSizes, $is_a_bulk);
134
+ }
135
+ $last_success_url = $this->fileUri;
136
+
137
+ }
138
+ // $imageUrl = $this->fileUri;
139
+ //$logstatus = 'Processed';
140
+ // $thumb = wp_get_attachment_thumb_url($this->id);
141
+ RTA()->ajax()->add_status('regenerate_success', array('thumb' => $last_success_url));
142
+
143
+ } else {
144
+
145
+ $debug_filename = (strlen($this->fileUri) > 0) ? $this->fileUri : $this->filePath;
146
+ if ($this->does_exist) // Existing files, not image, can be attachments, zipfiles, pdf etc. Fail silently.
147
+ {
148
+ $mime = get_post_mime_type($this->id);
149
+ if (strpos($mime, 'image') !== false)
150
+ RTA()->ajax()->add_status('not_image', array('name' => $debug_filename));
151
+ }
152
+ else
153
+ {
154
+ Log::addDebug('File missing - Current Image reported as not an image', array($this->filePath) );
155
+ RTA()->ajax()->add_status('file_missing', array('name' => basename($debug_filename)) );
156
+ }
157
+
158
+ return false;
159
+ }
160
+
161
+ return true;
162
+ }
163
+
164
+ // Todo before doing this, function to remove thumbnails need to run somehow, without killing all.
165
+ public function saveNewMeta($updated_meta)
166
+ {
167
+ if (count($this->persistentMeta) > 0)
168
+ {
169
+ foreach($this->persistentMeta as $rsize => $add)
170
+ {
171
+ $updated_meta['sizes'][$rsize] = $add;
172
+ }
173
+ }
174
+
175
+ /* Retain in metadata main categories, if they are not set in the new metadata.
176
+ * This is for custom data that may be set by others, but will be removed upon regen.
177
+ * Of the main categories (sizes, width, file etc ) they are fixed format, so should always be present, regardless of content.
178
+ */
179
+ foreach($this->metadata as $key => $data)
180
+ {
181
+ if (! isset($updated_meta[$key]))
182
+ {
183
+ $updated_meta[$key] = $data;
184
+ }
185
+ }
186
+
187
+ $result = array();
188
+
189
+ if ($this->do_metacheck && isset($updated_meta['sizes']))
190
+ {
191
+ Log::addDebug('Do metaCheck now for ' . $this->id);
192
+ foreach($updated_meta['sizes'] as $size => $sizedata)
193
+ {
194
+ $thumbfile = $this->getDir() . $sizedata['file'];
195
+ if (! file_exists($thumbfile))
196
+ {
197
+ Log::addDebug('Thumbfile not existing. Unsetting this size', array($size, $thumbfile, $this->id));
198
+ unset($updated_meta['sizes'][$size]);
199
+ }
200
+ }
201
+ }
202
+
203
+ $result['update'] = wp_update_attachment_metadata($this->id, $updated_meta);
204
+ $this->metadata = wp_get_attachment_metadata($this->id);
205
+
206
+ if ($this->do_cleanup)
207
+ {
208
+ $result = $this->clean($result);
209
+ }
210
+
211
+ return $result;
212
+ }
213
+
214
+ public function disable_scaling()
215
+ {
216
+ return false;
217
+ }
218
+
219
+ public function capture_generate_sizes($full_sizes)
220
+ {
221
+ $do_regenerate_sizes = RTA()->admin()->getOption('process_image_sizes'); // $this->viewControl->process_image_sizes; // to images to be regenerated.
222
+ $process_options = RTA()->admin()->getOption('process_image_options'); // $this->viewControl->process_image_options; // the setting options for each size.
223
+
224
+ // imageMetaSizes is sizeName => Data based array of WP metadata.
225
+ $imageMetaSizes = $this->getCurrentSizes();
226
+
227
+ $prevent_regen = array();
228
+ foreach($do_regenerate_sizes as $rsize)
229
+ {
230
+ // 1. Check if size exists, if not, needs generation anyhow.
231
+ if (! isset($imageMetaSizes[$rsize]))
232
+ {
233
+ Log::addDebug("Image Meta size setting missing - $rsize ");
234
+ continue;
235
+ }
236
+
237
+ // 2. Check meta info (file) from the current meta info we have.
238
+ $metaSize = $imageMetaSizes[$rsize];
239
+ $overwrite = isset($process_options[$rsize]['overwrite_files']) ? $process_options[$rsize]['overwrite_files'] : false; // 3. Check if we keep or overwrite.
240
+
241
+ if (! $overwrite)
242
+ {
243
+ // thumbFile is RELATIVE. So find dir via main image.
244
+ $thumbFile = $this->getDir() . $metaSize['file'];
245
+ //Log::addDebug('Preventing overwrite of - ' . $thumbFile);
246
+ if (file_exists($thumbFile)) // 4. Check if file is really there
247
+ {
248
+ $prevent_regen[] = $rsize;
249
+ // Add to current Image the metaSize since it will be dropped by the metadata redoing.
250
+ Log::addDebug('File exists on ' . $rsize . ' ' . $thumbFile . ' - skipping regen - prevent overwrite');
251
+ $this->addPersistentMeta($rsize, $metaSize);
252
+ }
253
+ }
254
+ }
255
+
256
+
257
+ // 5. Drop the 'not to be' regen. images from the sizes so it will not process.
258
+ $do_regenerate_sizes = array_diff($do_regenerate_sizes, $prevent_regen);
259
+ Log::addDebug('Sizes going for regen - ' . count($do_regenerate_sizes) );
260
+
261
+ /* 6. If metadata should be cleansed of undefined sizes, remove them from the imageMetaSizes
262
+ * This is for sizes that are -undefined- in total by system sizes.
263
+ */
264
+ if (RTA()->process()->doCleanMetadata())
265
+ {
266
+ $system_sizes = RTA()->admin()->getOption('system_image_sizes'); //$this->viewControl->system_image_sizes;
267
+
268
+ $not_in_system = array_diff( array_keys($imageMetaSizes), array_keys($system_sizes) );
269
+ if (count($not_in_system) > 0)
270
+ Log::addDebug('Cleaning not in system', $not_in_system);
271
+
272
+ foreach($not_in_system as $index => $unset)
273
+ {
274
+ unset($imageMetaSizes[$unset]);
275
+ }
276
+ }
277
+
278
+ // 7. If unused thumbnails are not set for delete, keep the metadata intact.
279
+ if (! RTA()->process()->doRemoveThumbnails() )
280
+ {
281
+ $other_meta = array_diff( array_keys($imageMetaSizes), $do_regenerate_sizes, $prevent_regen);
282
+ if (count($other_meta) > 0)
283
+ Log::addDebug('Image sizes not selected, but not up for deletion', $other_meta);
284
+
285
+ foreach($other_meta as $size)
286
+ {
287
+ if (isset($imageMetaSizes[$size]))
288
+ $this->addPersistentMeta($size, $imageMetaSizes[$size]);
289
+ }
290
+ }
291
+
292
+ $returned_sizes = array();
293
+ foreach($full_sizes as $key => $data)
294
+ {
295
+ if (in_array($key, $do_regenerate_sizes))
296
+ {
297
+ $returned_sizes[$key] = $data;
298
+ }
299
+ }
300
+
301
+ $this->setRegeneratedSizes($do_regenerate_sizes);
302
+ return $returned_sizes;
303
+ }
304
+
305
+
306
+ /** This function tries to find related thumbnails to the current image. If there are not in metadata after our process, assume cleanup.
307
+ * This removes thumbnail files.
308
+ * See ShortPixel Image Optimiser's findThumbs method
309
+ **
310
+ **/
311
+ public function clean()
312
+ {
313
+ $mainFile = $this->filePath;
314
+ $exclude = array();
315
+
316
+ if (isset($this->metadata['sizes']))
317
+ {
318
+ foreach($this->metadata['sizes'] as $size => $data)
319
+ {
320
+ $exclude[] = $data['file'];
321
+ }
322
+ }
323
+ $result['excluding'] = $exclude;
324
+
325
+ $ext = pathinfo($mainFile, PATHINFO_EXTENSION); // file extension
326
+ $base = substr($mainFile, 0, strlen($mainFile) - strlen($ext) - 1);
327
+ $pattern = '/' . preg_quote($base, '/') . '-\d+x\d+\.'. $ext .'/';
328
+ $thumbsCandidates = @glob($base . "-*." . $ext);
329
+
330
+ $thumbs = array();
331
+ if(is_array($thumbsCandidates)) {
332
+ foreach($thumbsCandidates as $th) {
333
+ if(preg_match($pattern, $th)) {
334
+ $thumbs[]= $th;
335
+ }
336
+ }
337
+ if( count($this->customThumbSuffixes)
338
+ && !( is_plugin_active('envira-gallery/envira-gallery.php')
339
+ || is_plugin_active('soliloquy/soliloquy.php')
340
+ || is_plugin_active('soliloquy-lite/soliloquy-lite.php'))){
341
+ foreach ($this->customThumbSuffixes as $suffix){
342
+ $pattern = '/' . preg_quote($base, '/') . '-\d+x\d+'. $suffix . '\.'. $ext .'/';
343
+ foreach($thumbsCandidates as $th) {
344
+ if(preg_match($pattern, $th)) {
345
+ $thumbs[]= $th;
346
+ }
347
+ }
348
+ }
349
+ }
350
+ }
351
+
352
+ $result['removed'] = array();
353
+
354
+ foreach($thumbs as $thumb) {
355
+ if($thumb === $mainFile)
356
+ {
357
+ continue;
358
+ }
359
+ if (in_array(basename($thumb), $exclude))
360
+ {
361
+ continue;
362
+ }
363
+
364
+ if($thumb !== $mainFile) {
365
+ $status = @unlink($thumb);
366
+ $result['removed'][] = $thumb . "($status)";
367
+ }
368
+ }
369
+
370
+ return $result;
371
+ }
372
+
373
+ public function exists()
374
+ {
375
+ return $this->does_exist;
376
+ }
377
+
378
+ public function isImage()
379
+ {
380
+ return $this->is_image;
381
+ }
382
+
383
+ public function getUri()
384
+ {
385
+ return $this->fileUri;
386
+ }
387
+
388
+ public function getPath()
389
+ {
390
+ return $this->filePath;
391
+ }
392
+
393
+ public function getDir()
394
+ {
395
+ return $this->fileDir;
396
+ }
397
+
398
+ public function getMetaData()
399
+ {
400
+ return $this->metadata;
401
+ }
402
+
403
+
404
+
405
+ public function getCurrentSizes()
406
+ {
407
+ return (isset($this->metadata['sizes'])) ? $this->metadata['sizes'] : array();
408
+ }
409
+
410
+ public function addPersistentMeta($size, $data)
411
+ {
412
+ $this->persistentMeta[$size] = $data;
413
+ }
414
+
415
+ public function setRegeneratedSizes($sizes)
416
+ {
417
+ $this->regeneratedSizes = $sizes;
418
+ }
419
+
420
+ public function setCleanUp($clean)
421
+ {
422
+ $this->do_cleanup = $clean;
423
+ }
424
+
425
+ public function setMetaCheck($bool)
426
+ {
427
+ $this->do_metacheck = $bool;
428
+ }
429
+
430
+ public function fixMimeType($image_id)
431
+ {
432
+ $post = get_post($image_id);
433
+
434
+ if ($post->post_mime_type == '')
435
+ {
436
+ $mime = wp_get_image_mime($this->filePath);
437
+ $post->post_mime_type = $mime;
438
+ Log::addDebug('Fixing File Mime for ' . $this->filePath . ' new MIME - ' . $mime);
439
+ wp_update_post($post);
440
+ }
441
+ }
442
+
443
+ }
classes/Install.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace ReThumbAdvanced;
3
+ use \ReThumbAdvanced\ShortPixelLogger\ShortPixelLogger as Log;
4
+ use \ReThumbAdvanced\Notices\NoticeController as Notice;
5
+
6
+ use \ReThumbAdvanced\ShortQ as ShortQ;
7
+
8
+ class Install
9
+ {
10
+
11
+ /** The handler when user completely uninstalls the plugin */
12
+ public static function uninstall()
13
+ {
14
+
15
+ $process = new Process();
16
+ $q = $process->getQueue();
17
+ $q->uninstall();
18
+ }
19
+
20
+ /** Handler on activation */
21
+ public static function activate()
22
+ {
23
+
24
+ }
25
+
26
+ /** Handler on deactivate */
27
+ public static function deactivate()
28
+ {
29
+
30
+ }
31
+
32
+
33
+
34
+ }
classes/{rta-plugin.php → Plugin.php} RENAMED
@@ -2,41 +2,55 @@
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);
@@ -54,26 +68,21 @@ class rtaPlugin
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);
@@ -86,6 +95,21 @@ class rtaPlugin
86
 
87
  }
88
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  public function check_media_action()
90
  {
91
  if (isset($_GET['regen_action']) && $_GET['regen_action'] == 'regenerate_image_thumbnail')
@@ -100,15 +124,12 @@ class rtaPlugin
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
  }
@@ -117,25 +138,34 @@ class rtaPlugin
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');
@@ -155,10 +185,11 @@ class rtaPlugin
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
 
@@ -185,43 +216,79 @@ class rtaPlugin
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
  }
2
  namespace ReThumbAdvanced;
3
  use \ReThumbAdvanced\ShortPixelLogger\ShortPixelLogger as Log;
4
  use \ReThumbAdvanced\Notices\NoticeController as Notice;
5
+ use \ReThumbAdvanced\Controllers\AdminController as AdminController;
6
 
7
  // load runtime.
8
+ class Plugin
9
  {
10
+ protected static $instance;
11
 
12
  protected $paths = array('classes', 'classes/controllers');
13
 
14
  protected $front;
15
+ //protected $admin;
16
 
17
  public function __construct()
18
  {
19
  $log = Log::getInstance();
20
  if (Log::debugIsActive()) // upload dir can be expensive, so only do this when log is actually active.
21
  {
22
+ $uploaddir = wp_upload_dir(null, false, false);
23
  if (isset($uploaddir['basedir']))
24
  $log->setLogPath($uploaddir['basedir'] . "/rta_log");
25
  }
26
+ // $this->initRuntime();
27
 
28
  add_action( 'after_setup_theme', array( $this, 'add_custom_sizes' ) );
29
+ add_action( 'admin_init', array( $this, 'init' ) );
30
+ // add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ), 10 );
31
 
32
  add_action( 'admin_menu', array( $this, 'admin_menus' ) );
33
 
34
  add_filter( 'plugin_action_links_' . plugin_basename(RTA_PLUGIN_FILE), array($this, 'generate_plugin_links'));//for plugin settings page
35
+ }
36
+
37
+ public static function getInstance()
38
+ {
39
+ if (is_null(self::$instance))
40
+ self::$instance = new Plugin();
41
 
42
+ return self::$instance;
43
+ }
44
+
45
+ public static function namespaceit($name)
46
+ {
47
+ return '\ReThumbAdvanced\\' . $name;
48
  }
49
 
50
+
51
+ /*public function initRuntime()
52
  {
53
+
54
  foreach($this->paths as $short_path)
55
  {
56
  $directory_path = realpath(RTA_PLUGIN_PATH . $short_path);
68
  }
69
  }
70
  }
71
+ } */
72
 
73
  // load textdomain, init.
74
  public function init()
75
  {
76
  load_plugin_textdomain( 'regenerate-thumbnails-advanced', FALSE, RTA_LANG_DIR );
77
 
78
+ $this->front = new Front();
 
 
 
 
 
 
79
 
80
+ $ajax = AjaxController::getInstance(); //init
81
+ $ajax->init();
82
 
83
  add_filter('media_row_actions', array($this,'add_media_action'), 10, 2);
84
  add_action( 'add_meta_boxes', function () { add_meta_box('rta-link', __('Regenerate Thumbnails', 'enable-media-replace'), array($this, 'regenerate_meta_box'), 'attachment', 'side', 'low'); } );
85
+ add_filter('attachment_fields_to_edit', array($this, 'attachment_editor'), 10, 2);
86
 
87
  $this->check_media_action();
88
  //add_action('upload.php', array($this, 'check_media_action'), 10);
95
 
96
  }
97
 
98
+ public function ajax()
99
+ {
100
+ return AjaxController::getInstance();
101
+ }
102
+
103
+ public function process()
104
+ {
105
+ return Process::getInstance();
106
+ }
107
+
108
+ public function admin()
109
+ {
110
+ return Admin::getInstance();
111
+ }
112
+
113
  public function check_media_action()
114
  {
115
  if (isset($_GET['regen_action']) && $_GET['regen_action'] == 'regenerate_image_thumbnail')
124
  Notice::addError(__('No Attachment ID found, not regenerating','regenerate-thumbnails-advanced'));
125
  }
126
  else {
127
+ $result = RTA()->admin()->regenerate_single_image($attach_id);
 
128
  }
129
 
130
  $sendback = remove_query_arg( array('attachment_id', 'regen_action', '_wpnonce') );
 
131
  wp_redirect($sendback);
132
  exit();
 
133
  }
134
 
135
  }
138
  public function enqueue_scripts() {
139
 
140
  //wp_enqueue_script( 'jquery' );
141
+ wp_register_script('rta_js', RTA_PLUGIN_URL.'js/rta.js', array( 'jquery' ), RTA_PLUGIN_VERSION );
142
  wp_register_style( 'rta_css', RTA_PLUGIN_URL.'css/rta.css', array(), RTA_PLUGIN_VERSION );
143
  wp_register_style( 'rta_css_admin', RTA_PLUGIN_URL.'css/rta-admin-view.css', array(), RTA_PLUGIN_VERSION );
144
  wp_register_style( 'rta_css_admin_progress', RTA_PLUGIN_URL.'css/rta-admin-progress.css', array('rta_css_admin'), RTA_PLUGIN_VERSION );
145
 
146
+ $admin_url = admin_url( 'admin-ajax.php' );
147
+ if (Log::isManualDebug() )
148
+ {
149
+ $logLevel = Log::getLogLevel();
150
+ $admin_url = admin_url('admin-ajax.php?SHORTPIXEL_DEBUG=' . $logLevel);
151
+ }
152
 
153
  wp_localize_script( 'rta_js', 'rta_data', array(
154
+ 'ajaxurl' => $admin_url,
155
  'nonce_savesizes' => wp_create_nonce('rta_save_image_sizes'),
156
+ 'nonce_doprocess' => wp_create_nonce('rta_do_process'), // continue
157
+ 'nonce_generate' => wp_create_nonce('rta_generate'), // start / stop
158
  'strings' => array(
159
  'confirm_delete' => __('Are you sure you want to delete this image size?', 'regenerate-thumbnails-advanced'),
160
  'confirm_stop' => __("This will stop the regeneration process. You want to stop?", 'regenerate-thumbnails-advanced' ),
161
  'status_resume' => __("Interrupted process resumed", 'regenerate-thumbnails-advanced'),
162
  'status_start' => __('New Process started', 'regenerate-thumbnails-advanced'),
163
  'status_finish' => __('Process finished','regenerate-thumbnails-advanced' ),
164
+ 'status_fatal' => __('A fatal error occured!', 'regenerate-thumbnails-advanced'),
165
  ),
166
  'blog_id' => get_current_blog_id(),
167
+ 'process' => $this->ajax()->get_json_process(),
168
+ 'is_debug' => (Log::debugIsActive()) ? 1 : 0,
169
  ));
170
 
171
  do_action('rta_enqueue_scripts');
185
  }
186
 
187
  public function view_generate_thumbnails() {
188
+ $this->enqueue_scripts();
189
  wp_enqueue_style('rta_css');
190
  wp_enqueue_script('rta_js');
191
  //$rta_image_sizes = get_option( 'rta_image_sizes' );
192
+ $view = new AdminController();
193
  $view->show();
194
  }
195
 
216
  }
217
  }
218
 
 
 
 
 
 
 
219
  public function add_media_action( $actions, $post) {
220
 
221
+ $editurl = $this->getRegenerateLink($post->ID);
 
 
 
 
 
 
 
 
222
  $link = "href=\"$editurl\"";
223
+ $action = 'regenerate_image_thumbnail';
224
+
225
 
226
  $newaction[$action] = '<a ' . $link . ' aria-label="' . esc_attr(__("Regenerate Thumbnails", "regenerate-thumbnails-advanced")) . '" rel="permalink">' . esc_html(__("Regenerate Thumbnails", "regenerate-thumbnails-advanced")) . '</a>';
227
 
228
  return array_merge($actions,$newaction);
229
  }
230
 
231
+ /** Generates a link to single regen images.
232
+ * @param $post_id int Image Post Post ID
233
+ * @param $url String URL to base link on, otherwise current uRL will be used
234
+ */
235
+ private function getRegenerateLink($post_id, $url = '')
236
  {
237
  $action = 'regenerate_image_thumbnail';
238
 
239
  $url = add_query_arg(array(
240
  'regen_action' => $action,
241
+ 'attachment_id' => $post_id,
242
+ ), $url);
243
 
244
  $editurl = wp_nonce_url( $url, $action );
245
+ return $editurl;
246
+
247
+ }
248
+
249
+ /** The metabox in edit attachment view */
250
+ public function regenerate_meta_box($post)
251
+ {
252
+ $url = admin_url('post.php');
253
+ if (isset($_GET['post']))
254
+ $url = add_query_arg('post', intval($_GET['post']), $url);
255
+ if (isset($_GET['action']))
256
+ $url = add_query_arg('action', sanitize_text_field($_GET['action']), $url);
257
+
258
+ $editurl = $this->getRegenerateLink($post->ID, $url);
259
  $link = "href=\"$editurl\"";
260
 
261
  echo "<p><a class='button-secondary' $link>" . esc_html__("Regenerate Thumbnails", "regenerate-thumbnails-advanced") . "</a></p>";
262
  }
263
 
264
+ /** Adding a button to the attachements view popup */
265
+ public function attachment_editor($form_fields, $post)
266
+ {
267
+ $screen = null;
268
+ if (function_exists('get_current_screen'))
269
+ {
270
+ $screen = get_current_screen();
271
+
272
+ if(! is_null($screen) && $screen->id == 'attachment') // hide on edit attachment screen.
273
+ return $form_fields;
274
+ }
275
+
276
+ $url = admin_url('upload.php');
277
+ $url = add_query_arg('item', $post->ID, $url);
278
+
279
+ $editurl = $this->getRegenerateLink($post->ID, $url);
280
+
281
+ $link = "href=\"$editurl\"";
282
+ $form_fields["regenerate-thumbnails-advanced"] = array(
283
+ "label" => esc_html__("Regenerate Thumbnails", "enable-media-replace"),
284
+ "input" => "html",
285
+ "html" => "<p><a class='button-secondary' $link>" . esc_html__("Regenerate Thumbnails", "enable-media-replace") . "</a></p>"
286
+ );
287
+
288
+ return $form_fields;
289
+ }
290
+
291
+
292
+
293
+
294
  }
classes/Process.php ADDED
@@ -0,0 +1,278 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace ReThumbAdvanced;
3
+ use \ReThumbAdvanced\ShortPixelLogger\ShortPixelLogger as Log;
4
+ use \ReThumbAdvanced\ShortQ as ShortQ;
5
+
6
+ /** Class Process
7
+ * This class functions as glue between ShortQ and RTA. Responsible for enqueuing and process monitoring.
8
+ * Main class should be simply able to ask for process and it's status and act upon that.
9
+ */
10
+
11
+ class Process
12
+ {
13
+ const RTAQ_NAME = 'rtaq';
14
+ const RTA_SLUG = 'rta';
15
+
16
+ protected static $instance;
17
+
18
+ protected $total = 0;
19
+ protected $current = 0;
20
+ //protected $running = false;
21
+ //protected $is_queued = false;
22
+ //protected $status; // notifications.
23
+
24
+ // options.
25
+ protected $startstamp = -1;
26
+ protected $endstamp = -1;
27
+ protected $only_featured = false;
28
+ protected $remove_thumbnails = false;
29
+ protected $delete_leftmetadata = false;
30
+ protected $clean_metadata = false;
31
+
32
+ protected $query_prepare_limit = 1000; // amount of records to enqueue per go.
33
+ protected $run_start = 0;
34
+ protected $run_limit = 0;
35
+ // protected $query_chunk_size = 100;
36
+
37
+ protected $q;
38
+ protected $process_name = 'rta_image_process';
39
+
40
+ public function __construct()
41
+ {
42
+ $shortQ = new \ReThumbAdvanced\ShortQ\ShortQ(self::RTA_SLUG);
43
+ $this->q = $shortQ->getQueue(self::RTAQ_NAME);
44
+
45
+ $process = $this->get_process();
46
+ if ($process !== false)
47
+ $this->set_process($process);
48
+
49
+ $this->q->setOption('numitems', 3);
50
+ }
51
+
52
+ public static function getInstance()
53
+ {
54
+ if (is_null(self::$instance))
55
+ self::$instance = new Process();
56
+
57
+ return self::$instance;
58
+ }
59
+
60
+ public function getQueue()
61
+ {
62
+ return $this->q;
63
+ }
64
+
65
+ public function setTime($start, $end)
66
+ {
67
+ $this->startstamp = $start;
68
+ $this->endstamp = $end;
69
+ }
70
+
71
+ public function setRemoveThumbnails($bool)
72
+ {
73
+ $this->remove_thumbnails = $bool;
74
+ }
75
+
76
+ public function doRemoveThumbnails()
77
+ {
78
+ return $this->remove_thumbnails;
79
+ }
80
+
81
+
82
+ public function setDeleteLeftMeta($bool)
83
+ {
84
+ $this->delete_leftmetadata = $bool;
85
+ }
86
+
87
+ public function doDeleteLeftMeta()
88
+ {
89
+ return $this->delete_leftmetadata;
90
+ }
91
+
92
+ public function setCleanMetadata($bool)
93
+ {
94
+ $this->clean_metadata = $bool;
95
+ }
96
+
97
+ public function doCleanMetadata()
98
+ {
99
+ return $this->clean_metadata;
100
+ }
101
+
102
+ public function setOnlyFeatured($bool)
103
+ {
104
+ $this->only_featured = $bool;
105
+ }
106
+
107
+ public function get($name = false)
108
+ {
109
+ return $this->q->getStatus($name);
110
+ }
111
+
112
+ /** Starts a new generate process. Queries the totals based on form input
113
+ * @param $form Array with FormData
114
+ * @return boolean true if all went ok, false if error occured
115
+ * Status and errors can be gotten from process attribute.
116
+ */
117
+ public function start()
118
+ {
119
+ $this->end_process(); // reset all before starting.
120
+ $this->save_process();
121
+ $this->q->setStatus('preparing', true);
122
+ }
123
+
124
+ public function end()
125
+ {
126
+ $this->end_process();
127
+ }
128
+
129
+ // Chain function to limit runtimes in seconds..
130
+ public function limitTime($limit = 6)
131
+ {
132
+ if ($this->run_limit == 0)
133
+ {
134
+ $this->run_start = time();
135
+ $this->run_limit = time() + $limit;
136
+ }
137
+
138
+ if ($this->run_start <= $this->run_limit)
139
+ {
140
+ return true;
141
+ }
142
+ else
143
+ {
144
+ $this->run_limit = 0;
145
+ $this->run_start = 0;
146
+ }
147
+ return false;
148
+ }
149
+
150
+ public function prepare()
151
+ {
152
+ $result = 0;
153
+ $i = 0;
154
+ while( $this_result = $this->runEnqueue() )
155
+ {
156
+ if (! $this->limitTime() )
157
+ {
158
+ Log::addDebug('Prepare went over time, breaking');
159
+ break;
160
+ }
161
+
162
+ if ($i >= 50)
163
+ {
164
+ exit('Prepare loop went over maximum count!');
165
+ Log::addError('Fatal error on preparation. Hanging loop detected');
166
+ }
167
+
168
+ $result += $this_result;
169
+ $i++;
170
+ }
171
+
172
+ if ($this_result == false)
173
+ {
174
+ $this->q->setStatus('preparing', false);
175
+ $this->q->setStatus('running', true);
176
+ Log::addDebug('Preparing done, Starting run status');
177
+ }
178
+
179
+ return $result;
180
+ }
181
+
182
+ public function getItems()
183
+ {
184
+ return $this->q->dequeue();
185
+ }
186
+
187
+ protected function runEnqueue()
188
+ {
189
+ global $wpdb;
190
+ $lastId = $this->q->getStatus('last_item_id');
191
+
192
+ $query = 'SELECT ID FROM ' . $wpdb->posts . ' where post_type = %s ';
193
+ $prepare = array('attachment');
194
+
195
+ if ($this->startstamp > -1)
196
+ {
197
+ $query .= ' AND post_date >= %s ';
198
+ $prepare[] = date("Y-m-d H:i:s", $this->startstamp);
199
+ }
200
+ if ($this->endstamp > -1)
201
+ {
202
+ $query .= ' AND post_date <= %s ';
203
+ $prepare[] = date("Y-m-d H:i:s", $this->endstamp);
204
+ }
205
+
206
+ if ($this->only_featured)
207
+ {
208
+ $query .= ' and ID in (select meta_value from ' . $wpdb->postmeta . ' where meta_key = "_thumbnail_id")';
209
+ }
210
+
211
+ if ($lastId > 0)
212
+ {
213
+ $query .= ' and ID < %d'; // note the reverse here, due to order!
214
+ $prepare[] = $lastId;
215
+ Log::addDebug('Adding Last ID' . $lastId);
216
+ }
217
+
218
+ $query .= ' order by ID DESC ';
219
+
220
+ $query .= ' limit %d ';
221
+ $prepare[] = $this->query_prepare_limit;
222
+
223
+ $sql = $wpdb->prepare($query, $prepare);
224
+ Log::addTemp('Preparing SQL' . $sql);
225
+ $result = $wpdb->get_results($sql);
226
+ $resultCount = count($result);
227
+
228
+ // $chunks =
229
+ $items = array();
230
+
231
+ foreach($result as $index => $row)
232
+ {
233
+ $items[] = array('id' => $row->ID, 'value' => '');
234
+ }
235
+
236
+ $this->q->addItems($items);
237
+ $this->q->enqueue();
238
+
239
+ /** Keep looping preparing ( possible query limit reached ) until no new items are forthcoming. */
240
+ if ($resultCount > 0)
241
+ return $resultCount;
242
+
243
+ return false;
244
+
245
+ }
246
+
247
+ protected function get_process()
248
+ {
249
+ $process = get_option($this->process_name, false);
250
+ return $process;
251
+ }
252
+
253
+ protected function set_process($process)
254
+ {
255
+ foreach($process as $name => $value)
256
+ {
257
+ $this->{$name} = $value;
258
+ }
259
+ }
260
+
261
+ protected function save_process()
262
+ {
263
+ $data = array('startstamp' => $this->startstamp, 'endstamp' => $this->endstamp, 'only_featured' => $this->only_featured,
264
+ 'remove_thumbnails' => $this->remove_thumbnails, 'delete_leftmetadata' => $this->delete_leftmetadata, 'clean_metadata' => $this->clean_metadata, 'query_prepare_limit' => $this->query_prepare_limit,
265
+
266
+ );
267
+ update_option($this->process_name, $data, false);
268
+ }
269
+
270
+ protected function end_process()
271
+ {
272
+ $this->q->resetQueue();
273
+ delete_option($this->process_name);
274
+ }
275
+
276
+
277
+
278
+ } // process class
classes/controllers/rta_admin_controller.php DELETED
@@ -1,264 +0,0 @@
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/plugin.json ADDED
@@ -0,0 +1 @@
 
1
+ {"name":"ReThumbAdvanced\/plugin","description":"Regenerate Thumbnails Advanced ","type":"function","autoload":{"psr-4":{"ReThumbAdvanced":"classes/"}}}
classes/rta_admin.php DELETED
@@ -1,695 +0,0 @@
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_image.php DELETED
@@ -1,244 +0,0 @@
1
- <?php
2
- namespace ReThumbAdvanced;
3
- use \ReThumbAdvanced\ShortPixelLogger\ShortPixelLogger as Log;
4
-
5
-
6
- class rtaImage
7
- {
8
- protected $id;
9
-
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;
17
- protected $fileDir;
18
- protected $metadata = array();
19
-
20
- protected $persistentMeta = array();
21
- protected $regeneratedSizes = array();
22
-
23
- protected $customThumbSuffixes = array('_c', '_tl', '_tr', '_br', '_bl');
24
-
25
- public function __construct($image_id)
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.
57
- public function saveNewMeta($updated_meta)
58
- {
59
- if (count($this->persistentMeta) > 0)
60
- {
61
- foreach($this->persistentMeta as $rsize => $add)
62
- {
63
- $updated_meta['sizes'][$rsize] = $add;
64
- }
65
- }
66
-
67
- /* Retain in metadata main categories, if they are not set in the new metadata.
68
- * This is for custom data that may be set by others, but will be removed upon regen.
69
- * Of the main categories (sizes, width, file etc ) they are fixed format, so should always be present, regardless of content.
70
- */
71
- foreach($this->metadata as $key => $data)
72
- {
73
- if (! isset($updated_meta[$key]))
74
- {
75
- $updated_meta[$key] = $data;
76
- }
77
- }
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
-
98
- if ($this->do_cleanup)
99
- {
100
- $result = $this->clean($result);
101
- }
102
-
103
- return $result;
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
- **/
111
- public function clean()
112
- {
113
- $mainFile = $this->filePath;
114
- $exclude = array();
115
-
116
- if (isset($this->metadata['sizes']))
117
- {
118
- foreach($this->metadata['sizes'] as $size => $data)
119
- {
120
- $exclude[] = $data['file'];
121
- }
122
- }
123
- $result['excluding'] = $exclude;
124
-
125
- $ext = pathinfo($mainFile, PATHINFO_EXTENSION); // file extension
126
- $base = substr($mainFile, 0, strlen($mainFile) - strlen($ext) - 1);
127
- $pattern = '/' . preg_quote($base, '/') . '-\d+x\d+\.'. $ext .'/';
128
- $thumbsCandidates = @glob($base . "-*." . $ext);
129
-
130
- $thumbs = array();
131
- if(is_array($thumbsCandidates)) {
132
- foreach($thumbsCandidates as $th) {
133
- if(preg_match($pattern, $th)) {
134
- $thumbs[]= $th;
135
- }
136
- }
137
- if( count($this->customThumbSuffixes)
138
- && !( is_plugin_active('envira-gallery/envira-gallery.php')
139
- || is_plugin_active('soliloquy/soliloquy.php')
140
- || is_plugin_active('soliloquy-lite/soliloquy-lite.php'))){
141
- foreach ($this->customThumbSuffixes as $suffix){
142
- $pattern = '/' . preg_quote($base, '/') . '-\d+x\d+'. $suffix . '\.'. $ext .'/';
143
- foreach($thumbsCandidates as $th) {
144
- if(preg_match($pattern, $th)) {
145
- $thumbs[]= $th;
146
- }
147
- }
148
- }
149
- }
150
- }
151
-
152
- $result['removed'] = array();
153
-
154
- foreach($thumbs as $thumb) {
155
- if($thumb === $mainFile)
156
- {
157
- continue;
158
- }
159
- if (in_array(basename($thumb), $exclude))
160
- {
161
- continue;
162
- }
163
-
164
- if($thumb !== $mainFile) {
165
- $status = @unlink($thumb);
166
- $result['removed'][] = $thumb . "($status)";
167
- }
168
- }
169
-
170
- return $result;
171
- }
172
-
173
- public function exists()
174
- {
175
- return $this->does_exist;
176
- }
177
-
178
- public function isImage()
179
- {
180
- return $this->is_image;
181
- }
182
-
183
- public function getUri()
184
- {
185
- return $this->fileUri;
186
- }
187
-
188
- public function getPath()
189
- {
190
- return $this->filePath;
191
- }
192
-
193
- public function getDir()
194
- {
195
- return $this->fileDir;
196
- }
197
-
198
- public function getMetaData()
199
- {
200
- return $this->metadata;
201
- }
202
-
203
-
204
-
205
- public function getCurrentSizes()
206
- {
207
- return (isset($this->metadata['sizes'])) ? $this->metadata['sizes'] : array();
208
- }
209
-
210
- public function addPersistentMeta($size, $data)
211
- {
212
- $this->persistentMeta[$size] = $data;
213
- }
214
-
215
- public function setRegeneratedSizes($sizes)
216
- {
217
- $this->regeneratedSizes = $sizes;
218
- }
219
-
220
- public function setCleanUp($clean)
221
- {
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 CHANGED
@@ -10,11 +10,12 @@ section.regenerate {
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 {
@@ -34,10 +35,10 @@ section.regenerate {
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;
@@ -45,20 +46,44 @@ section.regenerate {
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;
@@ -118,6 +143,8 @@ section.regenerate {
118
  section.regenerate button.stop-process {
119
  position: absolute;
120
  bottom: 10px;
121
- right: 15px;
122
  font-weight: normal;
123
- text-transform: none; }
 
 
10
  width: 65%;
11
  justify-content: flex-start; }
12
  section.regenerate .rta_progress .rta_progress_view {
13
+ margin: 0 auto;
14
+ align-self: center; }
15
  section.regenerate .rta_progress .rta_progress_view svg.CircularProgressbar {
16
  display: inline-block;
17
  width: 200px;
18
+ padding: 0 0 15px 0; }
19
  section.regenerate .rta_progress .rta_progress_view svg.CircularProgressbar .CircularProgressbar-trail {
20
  stroke: #d6d6d6; }
21
  section.regenerate .rta_progress .rta_progress_view svg.CircularProgressbar .CircularProgressbar-path {
35
  fill: 999; }
36
  section.regenerate .rta_progress .images {
37
  padding: 15px;
 
 
38
  width: 60%; }
39
  section.regenerate .rta_progress .images h5 {
40
+ text-align: right; }
41
+ section.regenerate .rta_progress .images h4.thumb-label {
42
  text-align: center; }
43
  section.regenerate .rta_progress .images .thumbnail {
44
  text-align: center;
46
  section.regenerate .rta_progress .images .thumbnail img {
47
  max-width: 500px;
48
  max-height: 500px; }
49
+ @media (max-width: 1200px) {
50
+ section.regenerate .rta_progress .images {
51
+ min-height: 300px;
52
+ width: 100%; }
53
+ section.regenerate .rta_progress .images .thumbnail img {
54
+ opacity: 0.5;
55
+ max-width: 100%;
56
+ overflow: hidden; }
57
+ section.regenerate .rta_progress .rta_progress_view {
58
+ width: 200px;
59
+ height: 220px;
60
+ position: absolute;
61
+ left: 50%;
62
+ top: 50%;
63
+ margin-left: -100px;
64
+ margin-top: -120px; } }
65
  section.regenerate .rta_status_box {
66
  width: 35%;
67
+ min-width: 300px;
68
+ border-left: 1px solid #ccc;
69
+ position: relative;
70
+ z-index: 10; }
71
  section.regenerate .rta_status_box .rta_wait_loader {
72
  margin-top: 35px;
73
  padding-left: 20px;
74
+ opacity: 0;
75
+ position: relative;
76
+ z-index: 1; }
77
  section.regenerate .rta_status_box .rta_wait_loader .dashicons {
78
  animation: wait-spin 2000ms infinite linear;
79
+ animation-play-state: running;
80
  width: 35px;
81
  height: 35px;
82
  font-size: 35px;
83
  float: left;
84
  margin-right: 30px; }
85
+ section.regenerate .rta_status_box .rta_wait_loader.rta_panel_off .dashicons {
86
+ animation-play-state: paused; }
87
  section.regenerate .rta_status_box .rta_notices ul.statuslist {
88
  max-height: 350px;
89
  overflow-y: auto;
143
  section.regenerate button.stop-process {
144
  position: absolute;
145
  bottom: 10px;
146
+ left: 15px;
147
  font-weight: normal;
148
+ text-transform: none;
149
+ padding: 4px 20px;
150
+ font-size: 14px; }
css/rta-admin-view.css CHANGED
@@ -1,12 +1,14 @@
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; }
@@ -42,14 +44,13 @@
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;
@@ -78,14 +79,13 @@
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; }
@@ -107,20 +107,36 @@
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 {
@@ -160,7 +176,16 @@
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; }
@@ -205,3 +230,18 @@
205
  opacity: 0; }
206
  .rta-admin .window-down {
207
  opacity: 100; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  .rta-admin .two-panel-wrap {
2
  display: flex;
3
+ justify-content: space-between;
4
+ margin-bottom: 20px; }
5
+ @media (max-width: 1200px) {
6
+ .rta-admin .two-panel-wrap.settings-panels {
7
  flex-direction: column-reverse; }
8
+ .rta-admin .two-panel-wrap.settings-panels .rta-settings-wrap, .rta-admin .two-panel-wrap.settings-panels .rta-regenerate-wrap {
9
+ width: 100%;
10
+ max-width: none;
11
+ margin: 14px 0; } }
12
  .rta-admin h2 {
13
  font-size: 26px;
14
  padding-left: 8px; }
44
  border-color: #ff0000; }
45
  .rta-admin .rta-regenerate-wrap, .rta-admin .rta-settings-wrap {
46
  flex: 1;
 
47
  position: relative;
48
+ padding: 0 0 0 15px;
49
  background: #fff; }
50
  .rta-admin .rta-regenerate-wrap {
51
+ margin-right: 8px; }
52
  .rta-admin .rta-settings-wrap {
53
+ flex: 2; }
54
  .rta-admin button, .rta-admin .btn_add_more {
55
  color: white;
56
  background: #00bcd4;
79
  .rta-admin .option > label input {
80
  vertical-align: middle;
81
  display: inline-block;
 
82
  position: absolute;
83
  margin-top: 2px; }
84
  .rta-admin .option > label span {
85
  display: inline-block;
86
+ margin-left: 25px;
87
+ line-height: 20px; }
88
  .rta-admin .option .note {
 
89
  margin-left: 15px; }
90
  .rta-admin .option .note p {
91
  margin-top: 0; }
107
  padding: 5px 6px;
108
  margin-left: 25px; }
109
  .rta-admin .table {
110
+ display: flex;
111
+ flex-direction: column;
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
+ display: flex; }
 
118
  .rta-admin .table .header input.image_sizes_pname, .rta-admin .table .row input.image_sizes_pname {
119
+ max-width: 110px; }
120
+ .rta-admin .table .header input.image_sizes_name, .rta-admin .table .row input.image_sizes_name {
121
+ font-size: 10px;
122
+ border: 0;
123
+ background: unset;
124
+ margin: 0;
125
+ padding: 0; }
126
  .rta-admin .table .header span, .rta-admin .table .row span {
127
+ padding: 5px;
128
+ flex-basis: 100px; }
129
+ .rta-admin .table .header span:nth-of-type(1), .rta-admin .table .row span:nth-of-type(1) {
130
+ flex-basis: 120px; }
131
+ .rta-admin .table .header span:nth-of-type(4), .rta-admin .table .row span:nth-of-type(4) {
132
+ flex-basis: 150px; }
133
+ .rta-admin .table .header span button, .rta-admin .table .row span button {
134
+ padding: 0;
135
+ background: unset;
136
+ border: 0;
137
+ box-shadow: none; }
138
+ .rta-admin .table .header span button span, .rta-admin .table .row span button span {
139
+ color: #ff0000; }
140
  .rta-admin .table .row.proto, .rta-admin .table .rta_hidden {
141
  display: none; }
142
  .rta-admin .flex {
176
  display: flex;
177
  flex: 1; }
178
  .rta-admin .cleanup-wrapper .option .note {
179
+ flex: 2;
180
+ display: inline-block; }
181
+ @media (max-width: 1500px) {
182
+ .rta-admin .cleanup-wrapper .option {
183
+ flex-wrap: wrap; }
184
+ .rta-admin .cleanup-wrapper .option label {
185
+ width: 100%; }
186
+ .rta-admin .cleanup-wrapper .option .note {
187
+ width: 100%;
188
+ margin: 4px 0; } }
189
  .rta-admin .warning-removal {
190
  position: relative;
191
  text-decoration: line-through; }
230
  opacity: 0; }
231
  .rta-admin .window-down {
232
  opacity: 100; }
233
+ .rta-admin .rta-ad {
234
+ background: #fff;
235
+ border: 1px solid #eee;
236
+ padding: 16px;
237
+ margin: 20px 0;
238
+ display: flex;
239
+ align-items: center; }
240
+ .rta-admin .rta-ad .img-wrapper {
241
+ margin-right: 25px; }
242
+ .rta-admin .rta-ad h3, .rta-admin .rta-ad p {
243
+ margin: 6px 0; }
244
+ .rta-admin .rta-ad a {
245
+ font-size: 16px;
246
+ font-weight: 700;
247
+ text-decoration: underline; }
css/rta.css CHANGED
@@ -16,6 +16,12 @@ svg:not(:root) {
16
  img {
17
  vertical-align: middle;
18
  }
 
 
 
 
 
 
19
  #rtaContent .cpbParent .CircularProgressbar {
20
  display: inline-block;
21
  width: 200px;
16
  img {
17
  vertical-align: middle;
18
  }
19
+
20
+ .dashicons-editor-help {
21
+ text-decoration: none;
22
+ margin-top: -1px;
23
+ }
24
+
25
  #rtaContent .cpbParent .CircularProgressbar {
26
  display: inline-block;
27
  width: 200px;
images/del.png DELETED
Binary file
images/edit.png DELETED
Binary file
images/pdf.png DELETED
Binary file
images/robo-winky.png ADDED
Binary file
images/view.png DELETED
Binary file
includes/rta_class.php DELETED
@@ -1,418 +0,0 @@
1
- <?php
2
- /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3
-
4
- /**
5
- * Plugin main class that will control the whole skeleton and common functions
6
- *
7
- * PHP version 5
8
- *
9
- * @category Main
10
- * @package Regenerate Thumbnails ID SCOUT
11
- * @author Muhammad Atiq
12
- * @version 1.0.0
13
- * @since File available since Release 1.0.0
14
- */
15
-
16
- class RTA
17
- {
18
- protected $admin;
19
-
20
- //Plugin starting point. Will call appropriate actions
21
- public function __construct() {
22
-
23
- add_action( 'init', array( $this, 'rta_init' ) );
24
- /// add_action( 'wp_enqueue_scripts', array( $this, 'rta_enqueue_scripts' ), 10 );
25
- add_action( 'admin_enqueue_scripts', array( $this, 'rta_enqueue_scripts' ), 10 );
26
-
27
- //add_filter('media_row_actions', array($this,'add_media_action'), 10, 2);
28
-
29
- }
30
-
31
- //Plugin initialization
32
- public function rta_init() {
33
-
34
- do_action('rta_before_init');
35
- $this->admin = new RTA_Admin(); // admin hooks.
36
-
37
- load_plugin_textdomain( 'regenerate-thumbnails-advanced', FALSE, RTA_LANG_DIR );
38
-
39
- do_action('rta_after_init');
40
- }
41
-
42
- //Function will add CSS and JS files
43
- public function rta_enqueue_scripts() {
44
-
45
- do_action('rta_before_enqueue_scripts');
46
-
47
- //wp_enqueue_script( 'jquery' );
48
- wp_register_script( 'rta_js', RTA_PLUGIN_URL.'js/rta.js', array( 'jquery' ), RTA_PLUGIN_VERSION );
49
- wp_register_style( 'rta_css', RTA_PLUGIN_URL.'css/rta.css', array(), RTA_PLUGIN_VERSION );
50
-
51
- wp_localize_script( 'rta_js', 'rta_data', array(
52
- 'ajaxurl' => admin_url( 'admin-ajax.php' ),
53
- 'nonce_savesizes' => wp_create_nonce('rta_save_image_sizes'),
54
- 'nonce_generate' => wp_create_nonce('rta_regenerate_thumbnails'),
55
- 'confirm_delete' => __('Are you sure you want to delete this image size?', 'regenerate-thumbnails-advanced'),
56
- 'confirm_stop' => __("This will stop the regeneration process. You want to stop?", 'regenerate-thumbnails-advanced' ),
57
- ));
58
-
59
- do_action('rta_after_enqueue_scripts');
60
- }
61
-
62
- public function rta_format_size($bytes) {
63
-
64
- if ($bytes >= 1073741824) {
65
- $bytes = number_format($bytes / 1073741824, 2) . ' GB';
66
- }elseif ($bytes >= 1048576) {
67
- $bytes = number_format($bytes / 1048576, 2) . ' MB';
68
- }elseif ($bytes >= 1024) {
69
- $bytes = number_format($bytes / 1024, 2) . ' KB';
70
- }elseif ($bytes > 1) {
71
- $bytes = $bytes . ' bytes';
72
- }elseif ($bytes == 1) {
73
- $bytes = $bytes . ' byte';
74
- }else{
75
- $bytes = '0 bytes';
76
- }
77
- return $bytes;
78
- }
79
-
80
- public function rta_load_template( $template='', $for='front', $attr=array() ) {
81
-
82
- do_action( 'rta_before_load_template', $template, $for, $attr );
83
- $template = apply_filters( 'rta_template_to_load', $template, $for, $attr );
84
- $attr = apply_filters( 'rta_template_variables', $attr, $template, $for );
85
-
86
- if( empty($template) ) {
87
- return '';
88
- }
89
- if( is_array($attr) ) {
90
- extract($attr);
91
- }
92
- $html = '';
93
- $html = apply_filters( 'rta_before_template_html', $html, $template, $for, $attr );
94
- ob_start();
95
- require (RTA_PLUGIN_PATH.'templates/'.$for.'/'.$template.'.php');
96
- $html = ob_get_contents();
97
- ob_end_clean();
98
-
99
- do_action( 'rta_after_load_template', $template, $for, $attr, $html );
100
- $html = apply_filters( 'rta_after_template_html', $html, $template, $for, $attr );
101
-
102
- return $html;
103
- }
104
-
105
- public function rta_get_message_html( $message, $type = 'message' ) {
106
- do_action( 'rta_before_get_message_html', $message, $type );
107
- $message = apply_filters( 'rta_message_text', $message, $type );
108
- $type = apply_filters( 'rta_message_type', $type, $message );
109
-
110
- $html = '';
111
-
112
- $html = apply_filters( 'rta_before_message_html', $html, $message, $type );
113
-
114
- $attr = array( 'message' => $message, 'type' => $type );
115
-
116
- $html = $this->rta_load_template( $type, 'common', $attr );
117
-
118
- do_action( 'rta_after_get_message_html', $message, $type );
119
- $html = apply_filters( 'rta_after_message_html', $html, $message, $type );
120
-
121
- return $html;
122
- }
123
-
124
- public function debug($message)
125
- {
126
- if (defined('RTA_DEBUG'))
127
- {
128
- if (is_array($message) || is_object($message)) {
129
- $message = print_r($message, true);
130
- }
131
- file_put_contents(WP_CONTENT_DIR . '/rta.log' , '[' . date('Y-m-d H:i:s') . "] $message\n", FILE_APPEND);
132
- //file_put_contents(SHORTPIXEL_BACKUP_FOLDER . "/shortpixel_log", '[' . date('Y-m-d H:i:s') . "] $message\n", FILE_APPEND);
133
- }
134
- }
135
-
136
- /** Central function for JSON responses. Can be extended whenever needed */
137
- protected function jsonResponse($response)
138
- {
139
- wp_send_json($response);
140
- }
141
-
142
- /* @todo To Implement
143
-
144
- public function add_media_action( $actions, $post) {
145
- $url = admin_url( "upload.php");
146
- $url = add_query_arg(array(
147
- 'action' => 'media_replace',
148
- 'attachment_id' => $post->ID,
149
- ), $url);
150
- $action = "regenerate_thumbnails";
151
-
152
- $editurl = wp_nonce_url( $url, $action );
153
- $link = "href=\"$editurl\"";
154
-
155
- $newaction['regenerate'] = '<a ' . $link . ' aria-label="' . esc_html__("Replace media", "regenerate-thumbnails-advanced") . '" rel="permalink">' . esc_html__("Regenerate Thumbnails", "regenerate-thumbnails-advanced") . '</a>';
156
- return array_merge($actions,$newaction);
157
- }
158
- */
159
-
160
-
161
-
162
- /* [BS] Seems not in use */
163
- /*
164
- public function rta_add_record( $table = '', $data = array() ) {
165
-
166
- if( empty($data) || empty($table) ) {
167
- return false;
168
- }
169
-
170
- global $wpdb;
171
- $exclude = array( 'btnsave' );
172
- $attr = "";
173
- $attr_val = "";
174
- foreach( $data as $k=>$val ) {
175
- if(is_array($val)) {
176
- $val = maybe_serialize($val);
177
- }else{
178
- $val = $this->make_safe($val);
179
- }
180
- if( !in_array( $k, $exclude )) {
181
- if( $attr == "" ) {
182
- $attr.="`".$k."`";
183
- $attr_val.="'".$val."'";
184
- }else{
185
- $attr.=", `".$k."`";
186
- $attr_val.=", '".$val."'";
187
- }
188
- }
189
- }
190
- $sql = "INSERT INTO `".$wpdb->prefix.$table."` (".$attr.") VALUES (".$attr_val.")";
191
- $wpdb->query($sql);
192
- $lastid = $wpdb->insert_id;
193
- return $lastid;
194
- } */
195
-
196
- /* [BS] Seems not in use - All these function don't use Prepare SQL statement, which might be dangerous */
197
- /*
198
- public function rta_add_multiple_records( $table = '', $attr = array(), $data = array() ) {
199
- if( empty($data) || empty($table) || empty($attr) ) {
200
- return false;
201
- }
202
- global $wpdb;
203
- $exclude = array( 'btnsave' );
204
- $attr_str = "";
205
- foreach( $attr as $v ) {
206
- if( $attr_str == "" ) {
207
- $attr_str.="`".$v."`";
208
- }else{
209
- $attr_str.=", `".$v."`";
210
- }
211
- }
212
- $attr_val = "";
213
- foreach( $data as $row ) {
214
- if( $attr_val == '' ) {
215
- $attr_val.='(';
216
- }else{
217
- $attr_val.=',(';
218
- }
219
- $attr_val_row = '';
220
- foreach( $row as $k=>$val ) {
221
- if(is_array($val)) {
222
- $val = maybe_serialize($val);
223
- }else{
224
- $val = $this->make_safe($val);
225
- }
226
- if( !in_array( $k, $exclude )) {
227
- if( $attr_val_row == "" ) {
228
- $attr_val_row.="'".$val."'";
229
- }else{
230
- $attr_val_row.=", '".$val."'";
231
- }
232
- }
233
- }
234
- $attr_val.= $attr_val_row.')';
235
- }
236
- $sql = "INSERT INTO `".$wpdb->prefix.$table."` (".$attr_str.") VALUES ".$attr_val;
237
- $wpdb->query($sql);
238
- $lastid = $wpdb->insert_id;
239
- return $lastid;
240
- } */
241
-
242
- /* [BS] Seems not in use */
243
- /*
244
- public function rta_update_record( $table = '', $data = array(), $where = '' ) {
245
-
246
- if( empty($where) || empty($data) || empty($table) ) {
247
- return false;
248
- }
249
-
250
- global $wpdb;
251
- $exclude = array( 'id','btnsave' );
252
- $attr = "";
253
- foreach( $data as $k=>$val ) {
254
- if(is_array($val)) {
255
- $val = maybe_serialize($val);
256
- }else{
257
- $val = $this->make_safe($val);
258
- }
259
- if( !in_array( $k, $exclude )) {
260
- if( $attr == "" ) {
261
- $attr.="`".$k."` = '".$val."'";
262
- }else{
263
- $attr.=", `".$k."` = '".$val."'";
264
- }
265
- }
266
- }
267
- $sql = "UPDATE `".$wpdb->prefix.$table."` SET ".$attr." WHERE ".$where;
268
- $wpdb->query($sql);
269
-
270
- return true;
271
- } */
272
-
273
- /* [BS] Seems not in use */
274
- /*
275
- public function rta_del_record( $table = '', $where = '' ) {
276
-
277
- if( empty($where) || empty($table) ) {
278
- return false;
279
- }
280
-
281
- global $wpdb;
282
- $sql = "DELETE FROM `".$wpdb->prefix.$table."` WHERE ".$where;
283
- $wpdb->query($sql);
284
- return true;
285
- } */
286
-
287
- /* [BS] Get data from postmeta table. */
288
- public function rta_get_data( $table = '', $where = "1", $get_row = false, $attr = "*" ) {
289
-
290
- if( empty($table) ) {
291
- return false;
292
- }
293
-
294
- global $wpdb;
295
- // [BS] TODO - Query not prepared by default here.
296
- $sql = "SELECT ".$attr." FROM `".$wpdb->prefix.$table."` WHERE ".$where;
297
- if( $get_row ) {
298
- $data = $wpdb->get_row($sql);
299
- }else{
300
- $data = $wpdb->get_results($sql);
301
- }
302
-
303
- return $data;
304
- }
305
-
306
- /* [BS] Seems not in use. Also using a hardcoded key doesn't sound like a very strong function */
307
- /*
308
- public function rta_number_encrypt($data, $key = 'geyktksYMZNQU8lRTRSAIMFWSF2csvsq2we', $base64_safe=true, $shrink=true) {
309
- if ($shrink) $data = base_convert($data, 10, 36);
310
- $data = @mcrypt_encrypt(MCRYPT_ARCFOUR, $key, $data, MCRYPT_MODE_STREAM);
311
- if ($base64_safe) $data = str_replace('=', '', base64_encode($data));
312
- return $data;
313
- } */
314
-
315
- /* [BS] Seems not in use */
316
- /*
317
- public function rta_number_decrypt($data, $key = 'geyktksYMZNQU8lRTRSAIMFWSF2csvsq2we', $base64_safe=true, $expand=true) {
318
- if ($base64_safe) $data = base64_decode($data.'==');
319
- $data = @mcrypt_encrypt(MCRYPT_ARCFOUR, $key, $data, MCRYPT_MODE_STREAM);
320
- if ($expand) $data = base_convert($data, 36, 10);
321
- return $data;
322
- } */
323
-
324
-
325
- /* [BS] Replace this usages by sanitize_text_field which is made for this */
326
-
327
- public function make_safe( $variable ) {
328
-
329
- /* $variable = $this->strip_html_tags($variable);
330
- $bad = array("<", ">");
331
- $variable = str_replace($bad, "", $variable); */
332
-
333
- return sanitize_text_field($variable);
334
- }
335
-
336
- public function strip_html_tags( $text ) {
337
- $text = preg_replace(
338
- array(
339
- // Remove invisible content
340
- '@<head[^>]*?>.*?</head>@siu',
341
- '@<style[^>]*?>.*?</style>@siu',
342
- '@<script[^>]*?.*?</script>@siu',
343
- '@<object[^>]*?.*?</object>@siu',
344
- '@<embed[^>]*?.*?</embed>@siu',
345
- '@<applet[^>]*?.*?</applet>@siu',
346
- '@<noframes[^>]*?.*?</noframes>@siu',
347
- '@<noscript[^>]*?.*?</noscript>@siu',
348
- '@<noembed[^>]*?.*?</noembed>@siu'
349
- ),
350
- array(
351
- '', '', '', '', '', '', '', '', ''), $text );
352
-
353
- return strip_tags( $text);
354
- }
355
-
356
- public function array_sort($array, $on, $order='ASC'){
357
-
358
- $new_array = array();
359
- $sortable_array = array();
360
-
361
- if (count($array) > 0) {
362
- foreach ($array as $k => $v) {
363
- if (is_array($v)) {
364
- foreach ($v as $k2 => $v2) {
365
- if ($k2 == $on) {
366
- $sortable_array[$k] = $v2;
367
- }
368
- }
369
- } else {
370
- $sortable_array[$k] = $v;
371
- }
372
- }
373
-
374
- switch ($order) {
375
- case 'ASC':
376
- asort($sortable_array);
377
- break;
378
- case 'DESC':
379
- arsort($sortable_array);
380
- break;
381
- }
382
-
383
- foreach ($sortable_array as $k => $v) {
384
- $new_array[$k] = $array[$k];
385
- }
386
- }
387
-
388
- return $new_array;
389
- }
390
-
391
- // Function to safe redirect the page without warnings
392
- /* [BS] Seems not in use. Also wp_safe_redirect should be used for something like this */
393
- /*
394
- public function redirect( $url ) {
395
- echo '<script language="javascript">window.location.href="'.$url.'";</script>';
396
- exit();
397
- } */
398
-
399
- //Function will get called on plugin activation
400
- public static function rta_install() {
401
-
402
- do_action('rta_before_install');
403
-
404
- require_once RTA_PLUGIN_PATH.'includes/rta_install.php';
405
-
406
- do_action('rta_after_install');
407
- }
408
-
409
- // Function will get called on plugin de activation
410
- public static function rta_uninstall() {
411
-
412
- do_action('rta_before_uninstall');
413
-
414
- require_once RTA_PLUGIN_PATH.'includes/rta_uninstall.php';
415
-
416
- do_action('rta_after_uninstall');
417
- }
418
- } // class
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/rta_install.php DELETED
@@ -1,42 +0,0 @@
1
- <?php
2
- /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3
-
4
- /**
5
- * Class that will hold functionality for plugin activation
6
- *
7
- * PHP version 5
8
- *
9
- * @category Install
10
- * @package Regenerate Thumbnails ID SCOUT
11
- * @author Muhammad Atiq
12
- * @version 1.0.0
13
- * @since File available since Release 1.0.0
14
- */
15
-
16
- class RTA_Install extends RTA
17
- {
18
- public function __construct() {
19
-
20
- do_action('rta_before_install', $this );
21
-
22
- $options = get_option('rta_image_sizes');
23
-
24
- if ($options === false) // if no default settings are there; add.
25
- {
26
- $standard_sizes = array( 'thumbnail', 'medium', 'medium_large', 'large' ); // directly from media.php, hardcoded there.
27
- $process_image_options = array();
28
- foreach($standard_sizes as $name)
29
- {
30
- $process_image_options[$name] = array('overwrite_files' => false);
31
- }
32
- $options = array();
33
- $options['process_image_sizes'] = $standard_sizes;
34
- $options['process_image_options'] = $process_image_options;
35
- add_option('rta_image_sizes', $options);
36
- }
37
-
38
- do_action('rta_after_install', $this );
39
- }
40
- }
41
-
42
- $rta_install = new RTA_Install();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/rta_uninstall.php DELETED
@@ -1,26 +0,0 @@
1
- <?php
2
- /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3
-
4
- /**
5
- * Class that will hold functionality for plugin deactivation
6
- *
7
- * PHP version 5
8
- *
9
- * @category Uninstall
10
- * @package Regenerate Thumbnails ID SCOUT
11
- * @author Muhammad Atiq
12
- * @version 1.0.0
13
- * @since File available since Release 1.0.0
14
- */
15
-
16
- class RTA_Uninstall extends RTA
17
- {
18
- public function __construct() {
19
-
20
- do_action('rta_before_uninstall', $this );
21
-
22
- do_action('rta_after_uninstall', $this );
23
- }
24
- }
25
-
26
- $rta_uninstall = new RTA_Uninstall();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/rta.js CHANGED
@@ -3,20 +3,30 @@ jQuery(document).ready(function($){
3
  function rtaJS() {};
4
 
5
  rtaJS.prototype = {
6
- offset: 0,
7
- total: 0,
8
  is_interrupted_process: false, // was the process killed by reload earlier?
9
  in_process: false, // currently pushing it through.
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
 
@@ -37,7 +47,6 @@ rtaJS.prototype.init = function()
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) );
@@ -47,14 +56,20 @@ rtaJS.prototype.init = function()
47
 
48
  }
49
 
 
 
 
 
 
 
50
  // function to check if admin screen can start a new job.
51
  rtaJS.prototype.checkSubmitReady = function()
52
  {
53
  processReady = true;
54
 
55
  inputs = $('input[name^="regenerate_sizes"]:checked');
56
- if (inputs.length == 0)
57
- processReady = false;
58
 
59
  if (this.in_process || ! this.is_saved)
60
  processReady = false;
@@ -89,18 +104,28 @@ rtaJS.prototype.checkSubmitReady = function()
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)
@@ -122,7 +147,6 @@ 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);
@@ -136,7 +160,6 @@ rtaJS.prototype.startProcess = function (e)
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');
@@ -146,22 +169,30 @@ rtaJS.prototype.startProcess = function (e)
146
  dataType: 'json',
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
  });
@@ -180,84 +211,78 @@ rtaJS.prototype.resumeProcess = function()
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;
194
- total = this.total;
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({
208
- type: 'POST',
209
- dataType: 'json',
210
- url: rta_data.ajaxurl,
211
- data: {
212
- gen_nonce: rta_data.nonce_generate,
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
 
@@ -296,7 +321,7 @@ rtaJS.prototype.processStoppable = function()
296
 
297
  rtaJS.prototype.stopProcess = function()
298
  {
299
- if (confirm(rta_data.strings.confirm_stop))
300
  {
301
  this.is_stopped = true;
302
 
@@ -308,7 +333,7 @@ rtaJS.prototype.processStoppable = function()
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
  },
@@ -317,6 +342,7 @@ rtaJS.prototype.processStoppable = function()
317
  {
318
  self.add_status(response.status);
319
  }
 
320
  self.finishProcess();
321
  self.togglePanel('loading', false);
322
 
@@ -329,13 +355,20 @@ rtaJS.prototype.processStoppable = function()
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
 
@@ -346,16 +379,9 @@ rtaJS.prototype.processStoppable = function()
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)
@@ -439,6 +465,7 @@ rtaJS.prototype.processStoppable = function()
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);
@@ -480,7 +507,7 @@ rtaJS.prototype.processStoppable = function()
480
  var row = $('.row.proto').clone();
481
  $(row).attr('id', uniqueId);
482
  $(row).removeClass('proto');
483
- container.append(row.css('display', 'table-row') );
484
 
485
  container.find('.header').removeClass('rta_hidden');
486
  }
@@ -495,7 +522,7 @@ rtaJS.prototype.processStoppable = function()
495
  rtaJS.prototype.update_thumb_name = function(rowid) {
496
  if($("#"+rowid).length) {
497
  var old_name = $("#"+rowid+" .image_sizes_name").val();
498
- var name = "rta_thumb";//$("#"+rowid+" .image_sizes_name").val();
499
  var width = $("#"+rowid+" .image_sizes_width").val();
500
  var height = $("#"+rowid+" .image_sizes_height").val();
501
  var cropping = $("#"+rowid+" .image_sizes_cropping").val();
3
  function rtaJS() {};
4
 
5
  rtaJS.prototype = {
6
+ //offset: 0,
7
+ process: false,
8
  is_interrupted_process: false, // was the process killed by reload earlier?
9
  in_process: false, // currently pushing it through.
10
  is_stopped: false,
 
11
  is_saved: true,
12
+ is_debug: false, // use sparingly
13
+ status: []
14
  }
15
 
16
+
17
  rtaJS.prototype.init = function()
18
  {
19
+ if (rta_data.is_debug == 1)
20
+ {
21
+ this.is_debug= true;
22
+ console.log(rta_data); // let's go.
23
+ }
24
+
25
+ this.setStatusCodes();
26
  this.initProcess();
27
  this.checkSubmitReady();
28
 
29
+
30
  $('.select, .deselect').on('click', $.proxy(this.selectAll, this));
31
  $(document).on('change','input, select', $.proxy(this.checkSubmitReady, this));
32
 
47
  // Warnings, errors and such.
48
  $(document).on('change', 'input[name="del_associated_thumbs"]', $.proxy(this.toggleDeleteItems,this));
49
  $(document).on('change', 'input[name^="regenerate_sizes"]', $.proxy(this.toggleDeleteItems,this));
 
50
  this.toggleDeleteItems();
51
 
52
  $(document).on('change', '.rta-settings-wrap input, .rta-settings-wrap select', $.proxy(this.show_save_indicator, this) );
56
 
57
  }
58
 
59
+ /** Status codes need to sync with Ajax Controller */
60
+ rtaJS.prototype.setStatusCodes = function()
61
+ {
62
+ // this.status[
63
+ }
64
+
65
  // function to check if admin screen can start a new job.
66
  rtaJS.prototype.checkSubmitReady = function()
67
  {
68
  processReady = true;
69
 
70
  inputs = $('input[name^="regenerate_sizes"]:checked');
71
+ /* if (inputs.length == 0)
72
+ processReady = false; */
73
 
74
  if (this.in_process || ! this.is_saved)
75
  processReady = false;
104
  rtaJS.prototype.initProcess = function()
105
  {
106
  process = rta_data.process;
107
+ if (this.is_debug)
108
+ console.log(process);
109
+
110
+ this.process = process;
111
 
112
  if (process.running)
113
  this.in_process = process.running;
114
 
115
+ /*if (process.current)
116
+ this.offset = process.current;
117
 
118
  if (process.total)
119
  this.total = process.total;
120
+ */
121
+
122
+ if (process.running || process.preparing)
123
+ {
124
+ this.updateProgress();
125
+ this.resumeProcess();
126
+ }
127
+
128
 
 
 
129
  }
130
 
131
  rtaJS.prototype.selectAll = function(e)
147
  {
148
  e.preventDefault();
149
 
 
150
  this.resetPanels();
151
  this.togglePanel('main', true);
152
  this.togglePanel('loading', true);
160
  this.in_process = true;
161
  this.is_stopped = false;
162
  this.checkSubmitReady();
 
163
 
164
  var self = this;
165
  var form = $('#rtaform_process');
169
  dataType: 'json',
170
  url: rta_data.ajaxurl,
171
  data: {
172
+ nonce: rta_data.nonce_generate,
173
+ action: 'rta_start_process',
 
174
  genform: form.serialize(),
175
  },
176
  success: function (response) {
177
+
 
178
  if (response.status)
179
  {
180
  self.add_status(response.status);
181
  }
182
+ self.process = response;
183
+ self.updateProgress();
184
+ self.doProcess();
185
  },
186
+ error: function(xhr, text, error)
187
  {
188
+ var status = new Object;
189
+ if (this.is_debug)
190
+ console.log(xhr); // log response on error.
191
+
192
+ status.id = -1;
193
+ status.message = rta_data.strings.status_fatal;
194
+ status.error = true;
195
+ self.add_status([status]);
196
  self.finishProcess();
197
  }
198
  });
211
  status.error = true;
212
  this.add_status([status]);
213
 
214
+ this.doProcess();
215
  }
216
 
217
  // function for getting the next image in line.
218
+ rtaJS.prototype.doProcess = function()
219
  {
220
  this.togglePanel('loading', false);
221
 
222
  if (this.is_stopped)
223
  return; // escape if process has been stopped.
224
+ //offset = this.offset;
225
+ //total = this.total;
226
 
227
  this.in_process = true;
228
  this.checkSubmitReady();
229
+
230
  this.togglePanel('progress', true);
231
  this.processStoppable();
232
 
233
  var self = this;
234
 
235
+ $.ajax({
236
+ type: 'POST',
237
+ dataType: 'json',
238
+ url: rta_data.ajaxurl,
239
+ data: {
240
+ nonce: rta_data.nonce_doprocess,
241
+ action: 'rta_do_process',
242
+ type: 'submit',
243
+ // offset:offset,
244
+ //genform: JSON.stringify(form),
245
+ },
246
+ success: function (response) {
247
+ if (typeof response.items !== 'undefined') // return is a process var..
248
+ {
249
+ self.process = response;
250
+ self.updateProgress();
251
+ }
252
 
253
+ if (response.status)
254
+ {
255
+ self.add_status(response.status);
256
+ }
257
+ if( response.running || response.preparing ) {
 
 
 
 
 
 
 
 
258
 
259
+ if (! self.is_stopped)
260
  {
261
+ // self.offset = response.current;
262
+ setTimeout(function(){ self.doProcess(); },500);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
263
  }
264
+ }else{
265
+ self.finishProcess(); // done, or so.
266
+ }
267
 
268
+ },
269
+ error: function (response) {
270
+
271
+ var status = new Object;
272
+ status.id = -1;
273
+ status.message = response.status + ' ' + response.statusText + ' :: ';
274
+ status.error = true;
275
+ self.add_status([status]);
276
+
277
+ setTimeout(function(){ self.process(); },1000);
278
+
279
+ },
280
+ });
281
 
 
 
 
 
 
282
 
 
 
 
 
 
 
 
 
283
  //this.show_buttons();
284
+ // this.finishProcess();
285
+
286
 
287
  }
288
 
321
 
322
  rtaJS.prototype.stopProcess = function()
323
  {
324
+ if (window.confirm(rta_data.strings.confirm_stop))
325
  {
326
  this.is_stopped = true;
327
 
333
  dataType: 'json',
334
  url: rta_data.ajaxurl,
335
  data: {
336
+ nonce: rta_data.nonce_generate,
337
  action: 'rta_stop_process',
338
  type: 'submit',
339
  },
342
  {
343
  self.add_status(response.status);
344
  }
345
+ self.process = false;
346
  self.finishProcess();
347
  self.togglePanel('loading', false);
348
 
355
 
356
  rtaJS.prototype.updateProgress = function(percentage_done) {
357
 
358
+ if (! this.process)
359
+ return;
360
 
361
+ var items = parseInt(this.process.items);
362
+ var done = parseInt(this.process.done);
363
+ var total = (items + done);
364
+ var errors = this.process.errors;
365
+ //var offset = parseInt(this.offset);
366
+ //var total = parseInt(this.total);
367
+
368
+ if (done == 0 && total > 0)
369
  percentage_done = 0;
370
  else if (total > 0)
371
+ percentage_done = Math.round( (done/total) * 100);
372
  else
373
  percentage_done = 100;
374
 
379
  $(".CircularProgressbar-path").css("stroke-dashoffset",total_circle+"px");
380
  $(".CircularProgressbar-text").html(percentage_done+"%");
381
 
382
+ $('.progress-count .current').text(done);
383
  $('.progress-count .total').text(total);
384
+
 
 
 
 
 
 
 
385
  }
386
 
387
  rtaJS.prototype.togglePanel = function(name, show)
465
  else
466
  item_class = '';
467
 
468
+ // @todo Move these to named constants.
469
  if(item.status == 1) // status 1 is successfully regenerated thumbnail with URL in message.
470
  {
471
  this.showThumb(item.message);
507
  var row = $('.row.proto').clone();
508
  $(row).attr('id', uniqueId);
509
  $(row).removeClass('proto');
510
+ container.append(row); // row.css('display', 'flex')
511
 
512
  container.find('.header').removeClass('rta_hidden');
513
  }
522
  rtaJS.prototype.update_thumb_name = function(rowid) {
523
  if($("#"+rowid).length) {
524
  var old_name = $("#"+rowid+" .image_sizes_name").val();
525
+ var name = "rta_thumb";
526
  var width = $("#"+rowid+" .image_sizes_width").val();
527
  var height = $("#"+rowid+" .image_sizes_height").val();
528
  var cropping = $("#"+rowid+" .image_sizes_cropping").val();
js/rta.min.js CHANGED
@@ -1 +1 @@
1
- jQuery(document).ready(function(e){function t(){}(t.prototype={offset:0,total:0,is_interrupted_process:!1,in_process:!1,formcookie:null,is_saved:!0}).init=function(){this.checkSubmitReady(),e(".select, .deselect").on("click",e.proxy(this.selectAll,this)),e(document).on("change","input, select",e.proxy(this.checkSubmitReady,this)),e(document).on("click",".rta_regenerate",e.proxy(this.processInit,this)),e(document).on("change",".table.imagesizes input, .table.imagesizes select",e.proxy(this.image_size_changed,this)),e(document).on("click",'button[name="save_settings"]',e.proxy(this.image_size_changed,this)),e(document).on("click",".table.imagesizes .btn_remove_row",e.proxy(this.remove_image_size_row,this)),e(document).on("click","#btn_add_image_size",e.proxy(this.add_image_size_row)),e(document).on("click",".rta_error_link",e.proxy(function(){this.show_errorbox(!0)},this)),this.formcookie=this.get_form_cookie(),e(document).on("change",".rta-settings-wrap input, .rta-settings-wrap select",e.proxy(this.show_save_indicator,this)),e(document).on("change",'input[name^="regenerate_sizes"]',e.proxy(this.checkOptionsVisible,this));var t=parseInt(this.get_cookie("rta_offset")),s=parseInt(this.get_cookie("rta_total"));isNaN(t)||isNaN(s)||t<s&&(this.is_interrupted_process=!0,this.offset=t,this.total=s,this.process())},t.prototype.checkSubmitReady=function(){processReady=!0,inputs=e('input[name^="regenerate_sizes"]:checked'),0==inputs.length&&(processReady=!1),!this.in_process&&this.is_saved||(processReady=!1),processReady?(e("button.rta_regenerate").removeClass("disabled"),e("button.rta_regenerate").prop("disabled",!1)):(e("button.rta_regenerate").addClass("disabled"),e("button.rta_regenerate").prop("disabled",!0)),this.is_saved?(e('button[name="save_settings"]').prop("disabled",!0),e('button[name="save_settings"]').addClass("disabled"),e(".save_note").addClass("rta_hidden")):(e('button[name="save_settings"]').prop("disabled",!1),e('button[name="save_settings"]').removeClass("disabled"),e(".save_note").removeClass("rta_hidden"))},t.prototype.selectAll=function(t){var s=e(t.target).data("action"),r=e(t.target).data("target");checked="select"==s,e('input[name^="'+r+'"]').prop("checked",checked).trigger("change")},t.prototype.processInit=function(t){t.preventDefault(),this.unset_all_cookies(),this.show_errorbox(!1),this.hide_progress(),this.toggleShortPixelNotice(!1),this.show_wait(!0),this.in_process=!0,this.checkSubmitReady(),this.set_form_cookie();var s=this,r=this.get_form_cookie();e.ajax({type:"POST",dataType:"json",url:rta_data.ajaxurl,data:{gen_nonce:rta_data.nonce_generate,action:"rta_regenerate_thumbnails",type:"general",genform:JSON.stringify(r)},success:function(e){e.pCount>0?(s.offset=0,s.total=e.pCount,s.set_process_cookie(s.offset,s.total),s.process()):(s.finishProcess(),s.add_error(e.logstatus),s.show_errorlink(!0))}})},t.prototype.process=function(){offset=this.offset,total=this.total,this.in_process=!0,this.checkSubmitReady();var t=Math.round(offset/total*100);this.show_progress(t);var s=this,r=this.get_form_cookie();offset<total?e.ajax({type:"POST",dataType:"json",url:rta_data.ajaxurl,data:{gen_nonce:rta_data.nonce_generate,action:"rta_regenerate_thumbnails",type:"submit",offset:offset,genform:JSON.stringify(r)},success:function(t){t.offset<=total?("Processed"==t.logstatus&&e(".rta_progress .images img").attr("src",t.imgUrl),s.set_process_cookie(t.offset,total),s.offset=t.offset,setTimeout(function(){s.process()},1e3)):(s.set_cookie("rta_image_processed",e(".rta_progress .images img").attr("src")),s.show_errorlink(!0)),e.isArray(t.error)&&t.error.length>0&&s.add_error(t.logstatus)}}):(this.set_cookie("rta_image_processed",e(".rta_progress .images img").attr("src")),this.finishProcess(),this.show_errorlink(!0))},t.prototype.finishProcess=function(){this.in_process=!1,this.is_interrupted_process=!1,this.show_wait(!1),this.toggleShortPixelNotice(!0),this.checkSubmitReady()},t.prototype.show_progress=function(t){-1!=e(".rta_progress .images img").attr("src").indexOf("http")?e(".rta_progress .images").css("opacity",100):e(".rta_progress .images").css("opacity",0);var s=289.027;t>0&&(s=Math.round(s-s*t/100)),e(".CircularProgressbar-path").css("stroke-dashoffset",s+"px"),e(".CircularProgressbar-text").html(t+"%"),e(".rta_progress").is(":visible")||(this.show_wait(!1),e(".rta_progress").removeClass("rta_hidden"),e(".rta_progress").slideDown(),e(".rta_progress").css("display","inline-block"))},t.prototype.show_wait=function(t){t?e(".rta_wait_loader").show().removeClass("rta_hidden"):e(".rta_wait_loader").hide()},t.prototype.add_error=function(t){if(""!=t){var s="";if(e.isArray(t))for(var r=0;r<=t.length;r++)s=s+'<li class="list-group-item headLi">'+t[r]+"</li>";else s='<li class="list-group-item headLi">'+t+"</li>";e(".rta_error_box ul").append(s),this.set_cookie("rta_error_box_ul",e(".rta_error_box ul").html())}},t.prototype.show_errorbox=function(t){return t?!e(".rta_error_box").is(":visible")&&e(".rta_error_box ul li").length&&e(".rta_error_box").removeClass("rta_hidden").slideDown():(e(".rta_error_box").slideUp(10),e(".rta_error_box ul").html(""),e(".rta_error_link").slideUp(10)),!1},t.prototype.show_errorlink=function(){!e(".rta_error_link").is(":visible")&&e(".rta_error_box ul li").length&&e(".rta_error_link").removeClass("rta_hidden").slideDown()},t.prototype.hide_progress=function(){var e=jQuery;e(".rta_progress .images img").attr("src",""),e(".CircularProgressbar-path").css("stroke-dashoffset","289.027px"),e(".rta_progress .images").css("opacity",0),e(".rta_progress").slideUp(),e(".CircularProgressbar-text").html("0%")},t.prototype.unset_all_cookies=function(){this.set_cookie("rta_image_processed",""),this.set_cookie("rta_offset",""),this.set_cookie("rta_total",""),this.set_cookie("rta_last_settings","")},t.prototype.set_default_values=function(){},t.prototype.set_process_cookie=function(e,t){e=parseInt(e),t=parseInt(t),isNaN(e)||this.set_cookie("rta_offset",e),isNaN(t)||this.set_cookie("rta_total",t)},t.prototype.get_form_cookie=function(){var e=this.get_cookie("rta_last_settings");return formcookie={},e.length>0&&(formcookie=JSON.parse(e)),formcookie},t.prototype.set_form_cookie=function(){var t={};e("#frm_rta_image_sizes").find("input, select").each(function(){var s=e(this).val(),r=e(this).attr("name");return r.indexOf("image_sizes[")>=0||("checkbox"==e(this).attr("type")&&!e(this).prop("checked")||(matches=r.match(/(.*?)\[(.*)\]/),void(null!==matches?(t[matches[1]]||(t[matches[1]]=[]),t[matches[1]][matches[2]]=s):t[r]=s)))}),this.set_cookie("rta_last_settings",JSON.stringify(t),10)},t.prototype.set_cookie=function(e,t,s){var r=new Date;r.setTime(r.getTime()+24*s*60*60*1e3);var o="expires="+r.toUTCString();document.cookie=e+"="+t+";"+o+";path=/"},t.prototype.get_cookie=function(e){for(var t=e+"=",s=decodeURIComponent(document.cookie).split(";"),r=0;r<s.length;r++){for(var o=s[r];" "==o.charAt(0);)o=o.substring(1);if(0==o.indexOf(t))return o.substring(t.length,o.length)}return""},t.prototype.add_image_size_row=function(){var e=jQuery,t=e(".table.imagesizes"),s=Math.random().toString(36).substring(2)+(new Date).getTime().toString(36),r=e(".row.proto").clone();e(r).attr("id",s),e(r).removeClass("proto"),t.append(r.css("display","table-row")),t.find(".header").removeClass("rta_hidden")},t.prototype.image_size_changed=function(t){t.preventDefault();var s=e(t.target).parents(".row").attr("id");this.update_thumb_name(s),this.save_image_sizes()},t.prototype.update_thumb_name=function(t){if(e("#"+t).length){var s=e("#"+t+" .image_sizes_name").val(),r=e("#"+t+" .image_sizes_width").val(),o=e("#"+t+" .image_sizes_height").val(),i=e("#"+t+" .image_sizes_cropping").val(),a=e("#"+t+" .image_sizes_pname").val();r<=0&&(r=""),o<=0&&(o="");var n=("rta_thumb "+i+" "+r+"x"+o).toLowerCase().replace(/ /g,"_");e('input[name^="regenerate_sizes"][value="'+s+'"]').val(n),a.length<=0&&e('input[name^="regenerate_sizes"][value="'+s+'"]').text(n),e('input[name="keep_'+s+'"]').attr("name","keep_"+n),e("#"+t+" .image_sizes_name").val(n)}},t.prototype.save_image_sizes=function(){this.settings_doingsave_indicator(!0);var t=rta_data.nonce_savesizes,s=this;e.ajax({type:"POST",dataType:"json",url:rta_data.ajaxurl,data:{action:"rta_save_image_sizes",save_nonce:t,saveform:e("#rta_settings_form").serialize()},success:function(t){t.error||t.new_image_sizes&&(e(".thumbnail_select .checkbox-list").fadeOut(80).html(t.new_image_sizes).fadeIn(80),s.checkOptionsVisible()),s.is_saved=!0,s.settings_doingsave_indicator(!1),s.checkSubmitReady()}})},t.prototype.settings_doingsave_indicator=function(t){t?e(".form_controls .save_indicator").fadeIn(20):e(".form_controls .save_indicator").fadeOut(100)},t.prototype.show_save_indicator=function(){this.is_saved=!1,this.checkSubmitReady()},t.prototype.toggleShortPixelNotice=function(t){t?e(".shortpixel-bulk-notice, .shortpixel-notice").removeClass("rta_hidden"):e(".shortpixel-bulk-notice, .shortpixel-notice").addClass("rta_hidden")},t.prototype.remove_image_size_row=function(t){var s=e(t.target).parents(".row").attr("id");if(confirm(rta_data.confirm_delete)){var r=e("#"+s).find(".image_sizes_name").val();e('input[name^="regenerate_sizes"][value="'+r+'"]').remove(),e("#"+s).remove(),this.save_image_sizes()}},t.prototype.checkOptionsVisible=function(){e('input[name^="regenerate_sizes"]').each(function(){e(this).is(":checked")?e(this).parents(".item").find(".options").removeClass("hidden"):e(this).parents(".item").find(".options").addClass("hidden")})},window.rtaJS=new t,window.rtaJS.init()});
1
+ jQuery(document).ready(function(e){function s(){}(s.prototype={process:!1,is_interrupted_process:!1,in_process:!1,is_stopped:!1,is_saved:!0,is_debug:!1,status:[]}).init=function(){1==rta_data.is_debug&&(this.is_debug=!0,console.log(rta_data)),this.setStatusCodes(),this.initProcess(),this.checkSubmitReady(),e(".select, .deselect").on("click",e.proxy(this.selectAll,this)),e(document).on("change","input, select",e.proxy(this.checkSubmitReady,this)),e("#rtaform_process").on("submit",e.proxy(this.startProcess,this)),e(document).on("change",".table.imagesizes input, .table.imagesizes select",e.proxy(this.image_size_changed,this)),e(document).on("click",'button[name="save_settings"]',e.proxy(this.image_size_changed,this)),e(document).on("click",".table.imagesizes .btn_remove_row",e.proxy(this.remove_image_size_row,this)),e(document).on("click","#btn_add_image_size",e.proxy(this.add_image_size_row,this)),e(document).on("click",".stop-process",e.proxy(this.stopProcess,this)),e(document).on("click",".rta_success_box .modal-close",e.proxy(function(e){this.togglePanel("success",!1)},this)),e(document).on("change",'input[name="del_associated_thumbs"]',e.proxy(this.toggleDeleteItems,this)),e(document).on("change",'input[name^="regenerate_sizes"]',e.proxy(this.toggleDeleteItems,this)),this.toggleDeleteItems(),e(document).on("change",".rta-settings-wrap input, .rta-settings-wrap select",e.proxy(this.show_save_indicator,this)),e(document).on("change",'input[name^="regenerate_sizes"]',e.proxy(this.checkOptionsVisible,this)),e(".toggle-window").on("click",e.proxy(this.toggleWindow,this))},s.prototype.setStatusCodes=function(){},s.prototype.checkSubmitReady=function(){processReady=!0,inputs=e('input[name^="regenerate_sizes"]:checked'),!this.in_process&&this.is_saved||(processReady=!1),processReady?(e("button.rta_regenerate").removeClass("disabled"),e("button.rta_regenerate").prop("disabled",!1)):(e("button.rta_regenerate").addClass("disabled"),e("button.rta_regenerate").prop("disabled",!0)),this.is_saved?(e('button[name="save_settings"]').prop("disabled",!0),e('button[name="save_settings"]').addClass("disabled"),e(".save_note").addClass("rta_hidden")):(e('button[name="save_settings"]').prop("disabled",!1),e('button[name="save_settings"]').removeClass("disabled"),e(".save_note").removeClass("rta_hidden"))},s.prototype.initProcess=function(){process=rta_data.process,this.is_debug&&console.log(process),this.process=process,process.running&&(this.in_process=process.running),(process.running||process.preparing)&&(this.updateProgress(),this.resumeProcess())},s.prototype.selectAll=function(s){var t=e(s.target).data("action"),a=e(s.target).data("target");checked="select"==t,e('input[name^="'+a+'"]').prop("checked",checked).trigger("change")},s.prototype.startProcess=function(s){s.preventDefault(),this.resetPanels(),this.togglePanel("main",!0),this.togglePanel("loading",!0);var t=new Object;t.id=-1,t.message=rta_data.strings.status_start,t.error=!0,this.add_status([t]),this.in_process=!0,this.is_stopped=!1,this.checkSubmitReady();var a=this,i=e("#rtaform_process");e.ajax({type:"POST",dataType:"json",url:rta_data.ajaxurl,data:{nonce:rta_data.nonce_generate,action:"rta_start_process",genform:i.serialize()},success:function(e){e.status&&a.add_status(e.status),a.process=e,a.updateProgress(),a.doProcess()},error:function(e,s,t){var i=new Object;this.is_debug&&console.log(e),i.id=-1,i.message=rta_data.strings.status_fatal,i.error=!0,a.add_status([i]),a.finishProcess()}})},s.prototype.resumeProcess=function(){this.resetPanels(),this.togglePanel("main",!0),this.togglePanel("loading",!0);var e=new Object;e.id=-1,e.message=rta_data.strings.status_resume,e.error=!0,this.add_status([e]),this.doProcess()},s.prototype.doProcess=function(){if(this.togglePanel("loading",!1),!this.is_stopped){this.in_process=!0,this.checkSubmitReady(),this.togglePanel("progress",!0),this.processStoppable();var s=this;e.ajax({type:"POST",dataType:"json",url:rta_data.ajaxurl,data:{nonce:rta_data.nonce_doprocess,action:"rta_do_process",type:"submit"},success:function(e){void 0!==e.items&&(s.process=e,s.updateProgress()),e.status&&s.add_status(e.status),e.running||e.preparing?s.is_stopped||setTimeout(function(){s.doProcess()},500):s.finishProcess()},error:function(e){var t=new Object;t.id=-1,t.message=e.status+" "+e.statusText+" :: ",t.error=!0,s.add_status([t]),setTimeout(function(){s.process()},1e3)}})}},s.prototype.processStoppable=function(){var s=!1;this.in_process&&(s=!0),s?e(".stop-process").prop("disabled",!1):e(".stop-process").prop("disabled",!0)},s.prototype.finishProcess=function(){this.in_process=!1,this.is_interrupted_process=!1,this.togglePanel("success",!0),this.processStoppable();var e=new Object;e.id=-1,e.message=rta_data.strings.status_finish,e.error=!0,this.add_status([e]),this.checkSubmitReady()},s.prototype.stopProcess=function(){if(window.confirm(rta_data.strings.confirm_stop)){this.is_stopped=!0,this.togglePanel("loading",!0);var s=this;e.ajax({type:"POST",dataType:"json",url:rta_data.ajaxurl,data:{nonce:rta_data.nonce_generate,action:"rta_stop_process",type:"submit"},success:function(e){e.status&&s.add_status(e.status),s.process=!1,s.finishProcess(),s.togglePanel("loading",!1)}})}},s.prototype.updateProgress=function(s){if(this.process){var t=parseInt(this.process.items),a=parseInt(this.process.done),i=t+a,o=(this.process.errors,289.027);(s=0==a&&i>0?0:i>0?Math.round(a/i*100):100)>0&&(o=Math.round(o-o*s/100)),e(".CircularProgressbar-path").css("stroke-dashoffset",o+"px"),e(".CircularProgressbar-text").html(s+"%"),e(".progress-count .current").text(a),e(".progress-count .total").text(i)}},s.prototype.togglePanel=function(s,t){var a;switch(s){case"main":a="section.regenerate";break;case"loading":a=".rta_wait_loader";break;case"progress":a=".rta_progress_view";break;case"thumbnail":a=".rta_thumbnail_view";break;case"success":a=".rta_success_box";break;case"notices":a=".rta_notices"}var i=e(a).is(":visible");i&&0==e(a).css("opacity")&&(i=!1),t&&!i?e(a).hasClass("rta_hidden")?e(a).slideDown():e(a).css("opacity",1):!t&&i&&(e(a).hasClass("rta_hidden")?e(a).hide():e(a).css("opacity",0))},s.prototype.resetPanels=function(){this.togglePanel("loading",!1),this.togglePanel("progress",!1),this.togglePanel("thumbnail",!1),this.togglePanel("success",!1),this.togglePanel("notices",!1),e(".rta_notices .statuslist li").remove()},s.prototype.add_status=function(s){if(this.togglePanel("notices",!0),""!=s){for(var t="",a=0;a<s.length;a++){var i=s[a],o="";o=i.error?"error":"",1!=i.status?t=t+'<li class="list-group-item '+o+'">'+i.message+"</li>":this.showThumb(i.message)}e(".rta_status_box ul.statuslist").append(t)}},s.prototype.showThumb=function(s){this.togglePanel("thumbnail",!0),e(".rta_progress .images img").attr("src",s)},s.prototype.add_image_size_row=function(){var e=jQuery,s=e(".table.imagesizes"),t=Math.random().toString(36).substring(2)+(new Date).getTime().toString(36),a=e(".row.proto").clone();e(a).attr("id",t),e(a).removeClass("proto"),s.append(a),s.find(".header").removeClass("rta_hidden")},s.prototype.image_size_changed=function(s){s.preventDefault();var t=e(s.target).parents(".row").attr("id");this.update_thumb_name(t),this.save_image_sizes()},s.prototype.update_thumb_name=function(s){if(e("#"+s).length){var t=e("#"+s+" .image_sizes_name").val(),a=e("#"+s+" .image_sizes_width").val(),i=e("#"+s+" .image_sizes_height").val(),o=e("#"+s+" .image_sizes_cropping").val(),r=e("#"+s+" .image_sizes_pname").val();a<=0&&(a=""),i<=0&&(i="");var n=("rta_thumb "+o+" "+a+"x"+i).toLowerCase().replace(/ /g,"_");e('input[name^="regenerate_sizes"][value="'+t+'"]').val(n),r.length<=0&&e('input[name^="regenerate_sizes"][value="'+t+'"]').text(n),e('input[name="keep_'+t+'"]').attr("name","keep_"+n),e("#"+s+" .image_sizes_name").val(n)}},s.prototype.save_image_sizes=function(){this.settings_doingsave_indicator(!0);var s=rta_data.nonce_savesizes,t=this;e.ajax({type:"POST",dataType:"json",url:rta_data.ajaxurl,data:{action:"rta_save_image_sizes",save_nonce:s,saveform:e("#rta_settings_form").serialize()},success:function(s){s.error||s.new_image_sizes&&(e(".thumbnail_select .checkbox-list").fadeOut(80).html(s.new_image_sizes).fadeIn(80),t.checkOptionsVisible()),t.is_saved=!0,t.settings_doingsave_indicator(!1),t.checkSubmitReady(),t.toggleDeleteItems()}})},s.prototype.settings_doingsave_indicator=function(s){s?e(".form_controls .save_indicator").fadeIn(20):e(".form_controls .save_indicator").fadeOut(100)},s.prototype.show_save_indicator=function(){this.is_saved=!1,this.checkSubmitReady()},s.prototype.remove_image_size_row=function(s){var t=e(s.target).parents(".row").attr("id");if(confirm(rta_data.strings.confirm_delete)){var a=e("#"+t).find(".image_sizes_name").val();e('input[name^="regenerate_sizes"][value="'+a+'"]').remove(),e("#"+t).remove(),this.save_image_sizes()}},s.prototype.checkOptionsVisible=function(){e('input[name^="regenerate_sizes"]').each(function(){if(e(this).is(":checked")){e(this).parents(".item").find(".options").removeClass("hidden");var s=e(this).parents(".item").find('input[type="checkbox"]');void 0===e(s).data("setbyuser")&&(e(s).prop("checked",!0),e(s).data("setbyuser",!0))}else e(this).parents(".item").find(".options").addClass("hidden")})},s.prototype.toggleDeleteItems=function(){e(".checkbox-list label").removeClass("warning-removal"),e(".checkbox-list .icon-warning").remove();var s=e('input[name="del_associated_thumbs"]');if(e(s).is(":checked")){var t=!1;e('input[name^="regenerate_sizes"]').not(":checked").each(function(){e(this).parent("label").addClass("warning-removal"),e(this).parent("label").find("input").before("<span class='dashicons dashicons-no icon-warning'></span>"),t=!0}),t&&e("#warn-delete-items").removeClass("rta_hidden")}else e("#warn-delete-items").addClass("rta_hidden")},s.prototype.toggleWindow=function(s){var t=e(s.target);t.hasClass("toggle-window")||(t=e(s.target).parents(".toggle-window"));var a=e("#"+t.data("window"));a.hasClass("window-up")?(a.removeClass("window-up").addClass("window-down"),t.find("span.dashicons").removeClass("dashicons-arrow-down").addClass("dashicons-arrow-up")):(a.removeClass("window-down").addClass("window-up"),t.find("span.dashicons").addClass("dashicons-arrow-down").removeClass("dashicons-arrow-up"))},window.rtaJS=new s,window.rtaJS.init()});
language/rta_general.php DELETED
@@ -1,16 +0,0 @@
1
- <?php
2
- //Settings Page
3
- $rta_lang['settings'] = __( 'Settings', 'regenerate-thumbnails-advanced' );
4
- $rta_lang['misc_settings'] = __( 'Misc Settings', 'regenerate-thumbnails-advanced' );
5
- $rta_lang['btn_update'] = __( 'Update', 'regenerate-thumbnails-advanced' );
6
- $rta_lang['btn_upload'] = __( 'Upload', 'regenerate-thumbnails-advanced' );
7
- $rta_lang['txt_field_label'] = __( 'Text Field', 'regenerate-thumbnails-advanced' );
8
- $rta_lang['upload_field_label'] = __( 'Upload Field', 'regenerate-thumbnails-advanced' );
9
- $rta_lang['settings_save_message'] = __( 'Settings Saved Successfully!', 'regenerate-thumbnails-advanced' );
10
- $rta_lang['not_authorize_error'] = __( 'You are not authorized to do that task', 'regenerate-thumbnails-advanced' );
11
- $rta_lang['not_thumb_to_del'] = __( 'No thumbnail images found', 'regenerate-thumbnails-advanced' );
12
- $rta_lang['some_thumb_not_del'] = __( 'Some thumbnail images not deleted', 'regenerate-thumbnails-advanced' );
13
- $rta_lang['thumb_del_success'] = __( 'All thumbnails deleted successfully.', 'regenerate-thumbnails-advanced' );
14
- $rta_lang['featured_image_label'] = __( 'Featured image custom size', 'regenerate-thumbnails-advanced' );
15
- $rta_lang['no_featured_image_label'] = __( 'Non-featured image custom size', 'regenerate-thumbnails-advanced' );
16
- $rta_lang['image_sizes_save_message'] = __( 'Image Sizes Saved Successfully!', 'regenerate-thumbnails-advanced' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
readme.txt CHANGED
@@ -3,9 +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.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,6 +55,16 @@ The script stops but it will resume after you open the settings page of the plug
55
 
56
  == Changelog ==
57
 
 
 
 
 
 
 
 
 
 
 
58
  = 2.2.0 =
59
 
60
  Release date: 9th March 2020
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.4.1
7
  Requires PHP: 5.3
8
+ Stable tag: 2.3.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.3.0 =
59
+
60
+ Release date: 29th May 2020
61
+ * New system for queuing which should be more efficient;
62
+ * New - Added regenerate thumbnails button in edit-attachment screen;
63
+ * Fixed - Crash when regenerating image from edit media;
64
+ * Fixed - Queries for large amount of images should not timeout;
65
+ * Fixes for the responsiveness of the regeneration screen;
66
+ * Class loader moved to PSR-4.
67
+
68
  = 2.2.0 =
69
 
70
  Release date: 9th March 2020
regenerate-thumbnails-advanced.php CHANGED
@@ -3,7 +3,7 @@ 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
@@ -13,29 +13,31 @@ Domain Path: /languages
13
 
14
  // Make sure we don't expose any info if called directly
15
  if ( !function_exists( 'add_action' ) ) {
16
- echo "Hi there! I'm just a plugin, not much I can do when called directly.";
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' ) );
 
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.3.0
7
  Author: ShortPixel
8
  Author URI: https://shortpixel.com/
9
  License: GPLv2 or later
13
 
14
  // Make sure we don't expose any info if called directly
15
  if ( !function_exists( 'add_action' ) ) {
16
+ exit;
 
17
  }
18
 
19
+ define( 'RTA_PLUGIN_VERSION', '2.3.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 . 'build/shortpixel/autoload.php');
27
+ //require_once(RTA_PLUGIN_PATH . 'classes/rta_controller.php');
28
+ require_once(RTA_PLUGIN_PATH . 'classes/Plugin.php');
29
+
30
+ $loader = new Build\PackageLoader();
31
+ $loader->setComposerFile(RTA_PLUGIN_PATH . 'classes/plugin.json');
32
+ $loader->load(RTA_PLUGIN_PATH);
33
 
34
+ function RTA()
35
+ {
36
+ return Plugin::getInstance();
37
+ }
38
 
39
+ RTA();
40
 
41
+ register_uninstall_hook(RTA_PLUGIN_FILE, array('Install', 'uninstall'));
42
+ register_activation_hook(RTA_PLUGIN_FILE, array('Install', 'activate'));
43
+ register_deactivation_hook(RTA_PLUGIN_FILE, array('Install', 'deactivate'));
rta_admin.php DELETED
@@ -1,497 +0,0 @@
1
- <?php
2
- /**
3
- * Class that will hold functionality for admin side
4
- *
5
- * PHP version 5
6
- *
7
- * @category Admin Side Code
8
- * @package Regenerate Thumbnails Advanced
9
- * @author ShortPixel
10
- */
11
-
12
- class RTA_Admin extends RTA
13
- {
14
- const PERIOD_ALL = 0;
15
- const PERIOD_DAY = 1;
16
- const PERIOD_WEEK = 2;
17
- const PERIOD_MONTH = 3;
18
- const PERIOD_3MONTH = 4;
19
- const PERIOD_6MONTH = 5;
20
- const PERIOD_YEAR = 6;
21
-
22
- protected $viewControl = null; // controller that handles the admin page.
23
-
24
- //Admin side starting point. Will call appropriate admin side hooks
25
- public function __construct() {
26
- $this->customThumbSuffixes = array('_c', '_tl', '_tr', '_br', '_bl');
27
-
28
- do_action('rta_before_admin', $this );
29
- //All admin side code will go here
30
-
31
- add_action( 'admin_menu', array( $this, 'rta_admin_menus' ) );
32
- add_action( 'wp_ajax_rta_regenerate_thumbnails', array( $this, 'rta_regenerate_thumbnails') );
33
- //add_filter( 'image_size_names_choose', array( $this, 'rta_image_custom_sizes' ), 10, 1 );
34
- add_action( 'wp_ajax_rta_save_image_sizes', array($this,'view_generate_thumbnails_save' ) );
35
-
36
- add_filter( 'plugin_action_links_' . plugin_basename(RTA_PLUGIN_FILE), array(&$this, 'generate_plugin_links'));//for plugin settings page
37
-
38
- do_action('rta_after_admin', $this );
39
- }
40
-
41
- public function rta_admin_menus(){
42
- $title = __('Regenerate Thumbnails', 'regenerate-thumbnails-advanced');
43
- add_management_page($title, $title, 'manage_options', 'rta_generate_thumbnails', array( $this, 'view_generate_thumbnails' ));
44
- }
45
-
46
- public function generate_plugin_links($links) {
47
- $in = '<a href="tools.php?page=rta_generate_thumbnails">Settings</a>';
48
- array_unshift($links, $in);
49
- return $links;
50
-
51
- }
52
-
53
- /**
54
- * 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.
55
- * @param $image_id
56
- * @param $image_posts_to_delete
57
- * TODO Remove this pass by reference.
58
- */
59
- function rta_del_leftover_metadata($image_id, $fullsizepath, &$image_posts_to_delete) {
60
- $original_meta = wp_get_attachment_metadata($image_id);
61
- $allSizesMissing = true;
62
- $someSizesMissing = false;
63
- if(isset($original_meta['sizes']) && is_array($original_meta['sizes'])) {
64
- foreach ($original_meta['sizes'] as $key => $size) {
65
- if(isset($size['file'])) {
66
- $thumb = (is_array($size['file'])) ? $size['file'][0] : $size['file'];
67
- if(file_exists(trailingslashit(dirname($fullsizepath)) . $thumb)) {
68
- $allSizesMissing = false;
69
- } else {
70
- unset($original_meta['sizes'][$key]);
71
- $someSizesMissing = true;
72
- }
73
- }
74
- }
75
- }
76
- if($allSizesMissing) {
77
- $image_posts_to_delete[] = $image_id;
78
- } elseif($someSizesMissing) {
79
- wp_update_attachment_metadata($image_id, $original_meta);
80
- }
81
- }
82
-
83
- public function getQueryDate($period)
84
- {
85
- $date = false;
86
- $args = false;
87
- switch (intval($period)) {
88
- case self::PERIOD_ALL:
89
- break;
90
- case self::PERIOD_DAY:
91
- $date = '-1 day';
92
- $args = array('after' => '1 day ago', 'before' => 'tomorrow');
93
- break;
94
- case self::PERIOD_WEEK:
95
- $date = '-1 week';
96
- $args = array('after' => '1 week ago', 'before' => 'tomorrow');
97
- break;
98
- case self::PERIOD_MONTH:
99
- $date = '-1 month';
100
- $args = array('after' => '1 month ago', 'before' => 'tomorrow');
101
- break;
102
- case self::PERIOD_3MONTH:
103
- $date = '-3 month';
104
- $args = array('after' => '3 months ago', 'before' => 'tomorrow');
105
- break;
106
- case self::PERIOD_6MONTH:
107
- $date = '-6 month';
108
- $args = array('after' => '6 months ago', 'before' => 'tomorrow');
109
- break;
110
- case self::PERIOD_YEAR:
111
- $date = '-1 year';
112
- $args = array('after' => '1 year ago', 'before' => 'tomorrow');
113
- break;
114
- }
115
- $result = array('date' => $date, 'args' => $args);
116
- return $result;
117
- }
118
-
119
- public function rta_regenerate_thumbnails() {
120
- if (defined('DOING_AJAX') && DOING_AJAX)
121
- $json = true;
122
- else {
123
- $json = false;
124
- }
125
-
126
- $nonce = isset($_POST['gen_nonce'])? $_POST['gen_nonce'] : false;
127
- if (! wp_verify_nonce($nonce, 'rta_regenerate_thumbnails'))
128
- {
129
- $this->jsonResponse(array('error' => true, 'logstatus' => "Invalid Nonce", 'message' => "Site error, Invalid Nonce"));
130
- exit();
131
- }
132
-
133
- if (isset($_POST['genform']))
134
- {
135
- $data = json_decode(html_entity_decode(stripslashes($_POST['genform'])), true);
136
- }
137
- else {
138
- $this->jsonResponse(array('error' => true, 'logstatus' => "No Data", 'message' => "Site error, No Data"));
139
- }
140
-
141
- $this->debug('POST VARS'); $this->debug($data);
142
-
143
- $has_period = (isset($data['period']) && $data['period'] > 0) ? true : false;
144
- $is_featured_only = (isset($data['regenonly_featured']) ) ? true : false;
145
-
146
- $process_type = (isset($_POST['type'])) ? sanitize_text_field($_POST['type']) : false;
147
- $period = isset($data['period']) ? intval($data['period']) : -1;
148
-
149
- if (! $process_type)
150
- {
151
- $this->jsonResponse(array('error' => true, 'logstatus' => "No Process defined", 'message' => "No Process Defined"));
152
- }
153
-
154
- if ($process_type == 'general')
155
- {
156
- $posts_per_page = -1; // all
157
- $offset = 0; // all
158
- }
159
- elseif ($process_type == 'submit')
160
- {
161
- $posts_per_page = 1;
162
- $offset = isset($_POST['offset']) ? intval($_POST['offset']) : 0;
163
- }
164
-
165
- $query_args = array(
166
- 'post_type' => 'attachment',
167
- 'post_mime_type' => 'image',
168
- 'posts_per_page' => $posts_per_page,
169
- 'post_status' => 'any',
170
- 'offset' => $offset,
171
- );
172
-
173
- // 2. Check the period selection
174
- if (isset($data['period'])) {
175
- $period = intval($data['period']);
176
- $date_query = $this->getQueryDate($period);
177
-
178
- if (is_array($date_query['args']))
179
- {
180
- $query_args['date_query'] = $date_query['args'];
181
- }
182
- }
183
-
184
- if ($is_featured_only)
185
- {
186
- global $wpdb;
187
- $meta_query_args = array(
188
- array(
189
- 'key' => '_thumbnail_id',
190
- 'compare' => 'IN',
191
- ),
192
- );
193
-
194
- $sql = ' SELECT meta_value from ' . $wpdb->postmeta . ' where meta_key = "_thumbnail_id"';
195
- $result = $wpdb->get_col($sql);
196
- if (count($result) > 0)
197
- $query_args['post__in'] = array_values($result);
198
-
199
- if (count($result) == 0)
200
- {
201
- $return_arr = array('pCount' => 0, 'type' => $process_type, 'period' => $period);
202
- $this->jsonResponse($return_arr);
203
- }
204
-
205
- }
206
-
207
- // [BS] Both seem not to be in use anymore.
208
- if (! isset($data['startTime']))
209
- $data['startTime'] = 0;
210
- if (! isset($data['fromTo']))
211
- $data['fromTo'] = 0;
212
-
213
- $imageUrl='';
214
- $logstatus = '';
215
-
216
- switch ($process_type) {
217
- case 'general': // this function only gather amount of images to process, runs before 'submit'
218
-
219
- $the_query = new WP_Query($query_args);
220
- $this->debug('(General) Process Start with args'); $this->debug($query_args);
221
- $post_count = 0;
222
-
223
- if ($the_query->have_posts()) {
224
- $post_count = $the_query->post_count;
225
- }else{
226
- $logstatus = __('No images found for this period or none uploaded');
227
- //$error[] = array('offset' => 0, 'logstatus' => $logstatus, 'imgUrl' => '', 'startTime' => '', 'fromTo' => '', 'type' => $process_type, 'period' =>'');
228
- $finalResult = array('offset' => 0, 'error' => 1,'pCount'=>0, 'logstatus' => $logstatus, 'imgUrl' => '', 'type' => $process_type, 'period' =>'');
229
- //header('Content-Type: application/json');
230
- //echo json_encode($finalResult);
231
- $this->jsonResponse($finalResult);
232
- exit();
233
- }
234
- wp_reset_query();
235
- wp_reset_postdata();
236
-
237
- if (!isset($date) || empty($date)) {
238
- $date = '';
239
- }
240
- delete_option('rta_get_all_files');
241
- $return_arr = array('pCount' => $post_count, 'type' => $process_type, 'period' => $period);
242
- //header('Content-Type: application/json');
243
- //echo json_encode($return_arr);
244
- $this->jsonResponse($return_arr);
245
- exit();
246
- break;
247
- case 'submit': // submit does the image processing
248
- $logstatus = '';
249
- $error = array();
250
-
251
- $del_thumbs = isset($data['del_associated_thumbs']) ? true : false;
252
- $del_leftover_metadata = isset($data['del_leftover_metadata']) ? true : false;
253
- $bulk = ($period == 0) ? true : false;
254
-
255
- $this->viewControl = new rtaAdminController($this);
256
-
257
- $the_query = new WP_Query($query_args);
258
- $this->debug('Regenerate Process started with'); $this->debug($query_args);
259
-
260
- if ($the_query->have_posts()) {
261
-
262
- $image_posts_to_delete = array();
263
-
264
- // The process runs just 1 image per run here.
265
- while ($the_query->have_posts()) {
266
- $the_query->the_post();
267
- $image_id = $the_query->post->ID;
268
-
269
- // simplification
270
- $this->currentImage = new rtaImage($image_id);
271
- $fullsizepath = $this->currentImage->getPath();
272
-
273
- if ($del_thumbs)
274
- {
275
- $this->currentImage->setCleanUp(true);
276
- $this->debug('Image thumbnails will be cleaned');
277
- }
278
-
279
- $this->debug( (array) $this->currentImage );
280
-
281
- if($del_leftover_metadata && ! $this->currentImage->exists() ) { // !file_exists($fullsizepath) )
282
- $this->rta_del_leftover_metadata($image_id, $fullsizepath, $image_posts_to_delete);
283
- $this->debug('Image did not exist. Removing leftover metadata');
284
- continue; //the main image is missing, nothing to regenerate.
285
- }
286
-
287
- if (isset($data['mediaID'])){
288
- $image_id = intval($data['mediaID']);
289
- }
290
-
291
- $filename_only = $this->currentImage->getUri(); //wp_get_attachment_thumb_url($image_id);
292
-
293
- if ($this->currentImage->isImage() ) {
294
-
295
- @set_time_limit(900);
296
- do_action('shortpixel-thumbnails-before-regenerate', $image_id);
297
-
298
- //use the original main image if exists
299
- $backup = apply_filters('shortpixel_get_backup', $fullsizepath);
300
- if($backup && $backup !== $fullsizepath) {
301
- copy($fullsizepath, $backup . "_optimized_" . $image_id);
302
- copy($backup, $fullsizepath);
303
- }
304
-
305
- //$original_meta = wp_get_attachment_metadata($image_id);
306
-
307
- add_filter('intermediate_image_sizes_advanced', array($this, 'capture_generate_sizes'));
308
-
309
- $new_metadata = wp_generate_attachment_metadata($image_id, $fullsizepath);
310
-
311
- remove_filter('intermediate_image_sizes_advanced', array($this, 'capture_generate_sizes'));
312
-
313
- //restore the optimized main image
314
- if($backup && $backup !== $fullsizepath) {
315
- rename($backup . "_optimized_" . $image_id, $fullsizepath);
316
- }
317
-
318
- //get the attachment name
319
- if (is_wp_error($new_metadata)) {
320
- $error[] = array('offset' => ($offset + 1), 'error' => $error, 'logstatus' => $logstatus, 'imgUrl' => $filename_only, 'startTime' => $data['startTime'], 'fromTo' => $data['fromTo'], 'type' => $process_type, 'period' => $period);
321
- }
322
- if (empty($new_metadata)) {
323
- $filename_only = wp_get_attachment_url($image_id);
324
- $logstatus = '<b>'.basename($filename_only).'</b> is missing';
325
- $error[] = array('offset' => ($offset + 1), 'error' => $error, 'logstatus' => $logstatus, 'imgUrl' => $filename_only, 'startTime' => $data['startTime'], 'fromTo' => $data['fromTo'], 'type' => $process_type, 'period' => $period);
326
- } else {
327
-
328
- // going for the save.
329
- $original_meta = $this->currentImage->getMetaData();
330
- $result = $this->currentImage->saveNewMeta($new_metadata); // this here calls the regeneration.
331
- $this->debug('Result :');
332
- $this->debug($result);
333
- $this->debug($this->currentImage->getMetaData());
334
-
335
- $is_a_bulk = true; // we are sending multiple images.
336
- $regenSizes = isset($new_metadata['sizes']) ? $new_metadata['sizes'] : array();
337
-
338
- // Do not send if nothing was regenerated, otherwise SP thinks all needs to be redone
339
-
340
- if (count($regenSizes) > 0)
341
- {
342
- do_action('shortpixel-thumbnails-regenerated', $image_id, $original_meta, $regenSizes, $is_a_bulk);
343
- }
344
-
345
- }
346
- $imageUrl = $filename_only;
347
- $logstatus = 'Processed';
348
- $filename_only = wp_get_attachment_thumb_url($image_id);
349
- } else {
350
- $filename_only = wp_get_attachment_url($image_id);
351
- $logstatus = '<b>'.basename($filename_only).'</b> is missing or not an image file';
352
- $error[] = array('offset' => ($offset + 1), 'error' => $error, 'logstatus' => $logstatus, 'imgUrl' => $filename_only, 'startTime' => $data['startTime'], 'fromTo' => $data['fromTo'], 'type' => $process_type, 'period' => $period);
353
- }
354
-
355
- } // Post Loop
356
-
357
- foreach($image_posts_to_delete as $to_delete) {
358
- wp_delete_post($to_delete, true);
359
- }
360
- } else {
361
- $logstatus = 'No pictures uploaded';
362
- $error[] = array('offset' => 0, 'error' => $error, 'logstatus' => $logstatus, 'imgUrl' => '');
363
- }
364
- if (!extension_loaded('gd') && !function_exists('gd_info')) {
365
- $filename_only = 'No file';
366
- $logstatus = 'PHP GD library is not installed on your web server. Please install in order to have the ability to resize and crop images';
367
- $error[] = array('offset' => ($offset + 1), 'error' => $error, 'logstatus' => $logstatus, 'imgUrl' => $filename_only, 'startTime' => $data['startTime'], 'fromTo' => $data['fromTo'], 'type' => $process_type, 'period' => $period);
368
- }
369
- //increment offset
370
- $result = $offset + 1;
371
- if(!isset($filename_only)){
372
- $filename_only = 'No files';
373
- }
374
- $this->debug($error);
375
- $finalResult = array('offset' => ($offset + 1), 'error' => $error, 'logstatus' => $logstatus, 'imgUrl' => $filename_only, 'startTime' => $data['startTime'], 'fromTo' => $data['fromTo'], 'type' => $process_type, 'period' => $period);
376
- break;
377
- } // switch - end submit.
378
-
379
-
380
- $this->jsonResponse($finalResult);
381
- exit();
382
- }
383
-
384
- public function get_error($message)
385
- {
386
-
387
- }
388
-
389
- public function capture_generate_sizes($full_sizes)
390
- {
391
- // $this->debug('Ignoring Wordpress:'); $this->debug($ignored_sizes);
392
-
393
- $do_regenerate_sizes = $this->viewControl->process_image_sizes; //settings
394
- $process_options = $this->viewControl->process_image_options;
395
-
396
- $imageMetaSizes = $this->currentImage->getCurrentSizes();
397
- $this->debug('Image Meta Sizes');
398
- $this->debug($imageMetaSizes);
399
- $this->debug($process_options);
400
-
401
- $prevent_regen = array();
402
- foreach($do_regenerate_sizes as $rsize)
403
- {
404
- // 1. Check if size exists, if not, needs generation anyhow.
405
- if (! isset($imageMetaSizes[$rsize]))
406
- {
407
- $this->debug("Image Meta size setting missing - $rsize ");
408
- continue;
409
- }
410
-
411
- // 2. Check meta info (file) from the current meta info we have.
412
- $metaSize = $imageMetaSizes[$rsize];
413
- $overwrite = isset($process_options[$rsize]['overwrite_files']) ? $process_options[$rsize]['overwrite_files'] : false; // 3. Check if we keep or overwrite.
414
-
415
- if (! $overwrite)
416
- {
417
- // thumbFile is RELATIVE. So find dir via main image.
418
- $thumbFile = $this->currentImage->getDir() . $metaSize['file'];
419
- $this->debug('Preventing overwrite of - ' . $thumbFile);
420
- if (file_exists($thumbFile)) // 4. Check if file is really there
421
- {
422
- $prevent_regen[] = $rsize;
423
- // Add to current Image the metaSize since it will be dropped by the metadata redoing.
424
- $this->debug('File exists on ' . $rsize . ' ' . $thumbFile . ' - skipping regen');
425
- $this->currentImage->addPersistentMeta($rsize, $metaSize);
426
- }
427
- }
428
-
429
- }
430
-
431
- // 5. Drop the 'not to be' regen. images from the sizes so it will not process.
432
- $do_regenerate_sizes = array_diff($do_regenerate_sizes, $prevent_regen);
433
- $this->debug('Sizes going for regen - '); $this->debug($do_regenerate_sizes);
434
-
435
- $returned_sizes = array();
436
- foreach($full_sizes as $key => $data)
437
- {
438
- if (in_array($key, $do_regenerate_sizes))
439
- {
440
- $returned_sizes[$key] = $data;
441
- }
442
- }
443
-
444
- $this->currentImage->setRegeneratedSizes($do_regenerate_sizes);
445
- return $returned_sizes;
446
- }
447
-
448
-
449
-
450
- public function view_generate_thumbnails() {
451
- wp_enqueue_style('rta_css');
452
- wp_enqueue_script('rta_js');
453
- //$rta_image_sizes = get_option( 'rta_image_sizes' );
454
- $view = new rtaAdminController($this);
455
- $view->show();
456
-
457
- }
458
-
459
- /* Saves and generates JSON response */
460
- public function view_generate_thumbnails_save()
461
- {
462
- $json = true;
463
- $view = new rtaAdminController($this);
464
- $response = $view->save_image_sizes();
465
-
466
- if ($json)
467
- {
468
- $this->jsonResponse($response);
469
- }
470
- else
471
- {
472
- return $response;
473
- }
474
- }
475
-
476
- /* Probably outdated
477
- public function rta_settings() {
478
- do_action('rta_before_settings', $this, $rta_options );
479
-
480
- $attr = $rta_options;
481
- $attr['message'] = $message;
482
- $html = $this->rta_load_template( "settings", "admin", $attr );
483
- do_action('rta_after_settings', $this, $rta_options );
484
- echo $html;
485
- }
486
- */
487
- /*
488
- * Seems not in use.
489
- private function load_wp_media_uploader() {
490
-
491
- wp_enqueue_script('media-upload');
492
- wp_enqueue_script('thickbox');
493
- wp_enqueue_style('thickbox');
494
- $html = $this->rta_load_template( "load_media_upload_js", "admin" );
495
- echo $html;
496
- } */
497
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
rta_front.php DELETED
@@ -1,90 +0,0 @@
1
- <?php
2
- /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3
-
4
- /**
5
- * Class that will hold functionality for front side
6
- *
7
- * PHP version 5
8
- *
9
- * @category Front Side Code
10
- * @package Regenerate Thumbnails ID SCOUT
11
- * @author Muhammad Atiq
12
- * @version 1.0.0
13
- * @since File available since Release 1.0.0
14
- */
15
-
16
- class RTA_Front extends RTA
17
- {
18
- //Front side starting point. Will call appropriate front side hooks
19
- public function __construct() {
20
-
21
- do_action('rta_before_front', $this );
22
- //All front side code will go here
23
-
24
- add_action( 'after_setup_theme', array( $this, 'rta_after_theme_setup' ) );
25
- add_filter( 'image_size_names_choose', array( $this, 'rta_image_size_names_choose' ), 10, 1 );
26
- add_filter( 'jpeg_quality', array( $this, 'rta_jpeg_quality' ),10, 1);
27
-
28
- do_action('rta_after_front', $this );
29
- }
30
-
31
- public function rta_jpeg_quality( $quality ) {
32
- $rta_image_sizes = get_option( 'rta_image_sizes' );
33
- if(is_array($rta_image_sizes) && sizeof($rta_image_sizes) > 0){
34
- $jpeg_quality = isset($rta_image_sizes['jpeg_quality']) ? $rta_image_sizes['jpeg_quality'] : null;
35
- if(!empty($jpeg_quality)) {
36
- return (int)$jpeg_quality;
37
- }
38
- }
39
- return $quality;
40
- }
41
-
42
- public function rta_image_size_names_choose( $sizes ) {
43
-
44
- $rta_image_sizes = get_option( 'rta_image_sizes', false );
45
- if (! $rta_image_sizes) // option not set
46
- return $sizes;
47
- if (! isset($rta_image_sizes['image_sizes']))
48
- return $sizes;
49
-
50
- $image_sizes = $rta_image_sizes['image_sizes'];
51
-
52
- $rta_sizes = array();
53
- if(is_array($image_sizes) && count($image_sizes) > 0 && sizeof($image_sizes['name']) > 0){
54
- for($i=0;$i<sizeof($image_sizes['name']);$i++){
55
- $slug = $image_sizes['name'][$i];
56
- $name = $image_sizes['pname'][$i];
57
- $rta_sizes[$slug] = $name;
58
- }
59
-
60
- }
61
-
62
- $new_sizes = array_merge( $sizes, $rta_sizes );
63
- return $new_sizes;
64
- }
65
-
66
- public function rta_after_theme_setup() {
67
-
68
- $rta_image_sizes = get_option( 'rta_image_sizes', false);
69
- if (! $rta_image_sizes)
70
- return $rta_image_sizes;
71
-
72
- $image_sizes = isset($rta_image_sizes['image_sizes']) && is_array($rta_image_sizes['image_sizes']) ? $rta_image_sizes['image_sizes'] : array();
73
-
74
- if(count($image_sizes) > 0 && count($image_sizes['name']) > 0){
75
- for($i=0;$i<sizeof($image_sizes['name']);$i++){
76
- $crop = false;
77
- if($image_sizes['cropping'][$i]=='no_cropped'){
78
- $crop = false;
79
- }elseif($image_sizes['cropping'][$i]=='cropped') {
80
- $crop = true;
81
- }else{
82
- $crop = explode("_", $image_sizes['cropping'][$i]);
83
- }
84
- add_image_size( $image_sizes['name'][$i], $image_sizes['width'][$i], $image_sizes['height'][$i], $crop );
85
- }
86
- }
87
- }
88
- }
89
-
90
- $rta_front = new RTA_Front();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
scss/rta-admin-progress.scss CHANGED
@@ -1,10 +1,10 @@
 
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;
@@ -17,15 +17,18 @@ section.regenerate
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
  }
@@ -51,16 +54,12 @@ section.regenerate
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
@@ -75,22 +74,52 @@ section.regenerate
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;
@@ -98,6 +127,13 @@ section.regenerate
98
  margin-right: 30px;
99
 
100
  }
 
 
 
 
 
 
 
101
  }
102
  .rta_notices
103
  {
@@ -134,7 +170,6 @@ section.regenerate
134
  position: absolute;
135
  left: 30%;
136
  top: -5%;
137
- // height: 350px;
138
  width: 45%;
139
  margin-left: -200px;
140
  opacity: 0.9;
@@ -199,9 +234,11 @@ section.regenerate
199
  {
200
  position: absolute;
201
  bottom: 10px;
202
- right: 15px;
203
  font-weight: normal;
204
  text-transform: none;
 
 
205
  }
206
 
207
 
1
+ @import 'mixins';
2
 
3
  section.regenerate
4
  {
5
  background-color: #fff;
6
  margin-bottom: 200px; // space to WP footer.
7
 
 
8
  .rta_panel_off
9
  {
10
  opacity: 0;
17
  min-height: 310px;
18
  width: 65%;
19
  justify-content: flex-start;
20
+
21
+
22
  .rta_progress_view
23
  {
24
  margin: 0 auto;
25
+ align-self: center;
26
 
27
  svg.CircularProgressbar
28
  {
29
  display: inline-block;
30
  width: 200px;
31
+ padding: 0 0 15px 0;
32
  .CircularProgressbar-trail {
33
  stroke: #d6d6d6;
34
  }
54
  }
55
 
56
  .images {
 
 
57
  padding: 15px;
 
 
 
 
 
58
  width: 60%;
59
  h5 {
60
+ text-align: right;
61
+ }
62
+ h4.thumb-label {
63
  text-align: center;
64
  }
65
  .thumbnail
74
 
75
  }
76
 
77
+ @include breakpoint(0, 1200px)
78
+ {
79
+ .images
80
+ {
81
+ min-height: 300px;
82
+ width: 100%;
83
+ .thumbnail {
84
+
85
+ img { opacity: 0.5; max-width: 100%; overflow: hidden; }
86
+ }
87
+ }
88
+ .rta_progress_view
89
+ {
90
+ width: 200px;
91
+ height: 220px;
92
+ position: absolute;
93
+ left: 50%;
94
+ top: 50%;
95
+ margin-left: -100px;
96
+ margin-top: -120px;
97
+
98
+ }
99
+ }
100
+
101
  } // rta-progress (left)
102
 
103
 
104
  .rta_status_box
105
  {
106
  width: 35%;
107
+ min-width: 300px;
108
  border-left: 1px solid #ccc;
109
+ position: relative;
110
+ z-index: 10;
111
 
112
  .rta_wait_loader
113
  {
114
  margin-top: 35px;
115
  padding-left: 20px;
116
  opacity: 0;
117
+ position: relative;
118
+ z-index: 1;
119
  //display:none;
120
  .dashicons {
121
  animation: wait-spin 2000ms infinite linear;
122
+ animation-play-state: running;
123
  width: 35px;
124
  height: 35px;
125
  font-size: 35px;
127
  margin-right: 30px;
128
 
129
  }
130
+ &.rta_panel_off // don't run when not visible.
131
+ {
132
+ .dashicons
133
+ {
134
+ animation-play-state: paused;
135
+ }
136
+ }
137
  }
138
  .rta_notices
139
  {
170
  position: absolute;
171
  left: 30%;
172
  top: -5%;
 
173
  width: 45%;
174
  margin-left: -200px;
175
  opacity: 0.9;
234
  {
235
  position: absolute;
236
  bottom: 10px;
237
+ left: 15px;
238
  font-weight: normal;
239
  text-transform: none;
240
+ padding: 4px 20px;
241
+ font-size: 14px;
242
  }
243
 
244
 
scss/rta-admin-view.scss CHANGED
@@ -6,13 +6,19 @@
6
  {
7
  display: flex;
8
  justify-content: space-between;
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
  }
@@ -75,24 +81,23 @@
75
 
76
  .rta-regenerate-wrap, .rta-settings-wrap
77
  {
78
- //width: 50%; float: left;
79
  flex: 1;
80
- //min-height: 600px;
81
- margin-bottom: 20px;
82
  position: relative;
83
- //max-width: 49%;
84
- padding: 0 15px;
85
  background: #fff;
 
86
  }
87
 
88
  .rta-regenerate-wrap
89
  {
90
- max-width: 35%;
 
91
  }
92
 
93
  .rta-settings-wrap
94
  {
95
- max-width: 60%;
 
96
  }
97
 
98
  %button
@@ -143,6 +148,8 @@
143
  {
144
  display: inline-block;
145
  margin-left: 25px;
 
 
146
  }
147
  }
148
  .note
@@ -191,20 +198,52 @@
191
  .table
192
  {
193
  //flex-wrap: wrap;
194
- table-layout: fixed;
195
- display: table;
 
 
 
 
196
  border-spacing: 10px 0;
197
  border: 1px solid #eee;
198
  word-wrap: normal;
199
  white-space: nowrap;
200
 
201
  .header, .row {
202
- width: 100%;
203
- display: table-row;
204
 
205
- input.image_sizes_pname { max-width: 180px; }
206
-
207
- span { display: table-cell; padding: 5px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208
  //min-width: 100px;
209
  }
210
  }
@@ -264,7 +303,16 @@
264
  {
265
  display: flex;
266
  flex: 1;
267
- .note { flex: 2; }
 
 
 
 
 
 
 
 
 
268
  }
269
  }
270
 
@@ -345,5 +393,26 @@
345
  opacity: 100;
346
  }
347
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
348
 
349
  } // class rta-admin
6
  {
7
  display: flex;
8
  justify-content: space-between;
9
+ margin-bottom: 20px;
10
+
11
+ &.settings-panels {
12
+ @include breakpoint(0,1200px)
13
  {
14
+ flex-direction: column-reverse;
15
+ .rta-settings-wrap, .rta-regenerate-wrap
16
+ {
17
+ width: 100%;
18
+ max-width: none;
19
+ margin: 14px 0;
20
+ }
21
+
22
  }
23
  }
24
  }
81
 
82
  .rta-regenerate-wrap, .rta-settings-wrap
83
  {
 
84
  flex: 1;
 
 
85
  position: relative;
86
+ padding: 0 0 0 15px;
 
87
  background: #fff;
88
+
89
  }
90
 
91
  .rta-regenerate-wrap
92
  {
93
+ //max-width: 35%;
94
+ margin-right: 8px;
95
  }
96
 
97
  .rta-settings-wrap
98
  {
99
+ //max-width: 60%;
100
+ flex: 2;
101
  }
102
 
103
  %button
148
  {
149
  display: inline-block;
150
  margin-left: 25px;
151
+ line-height: 20px;
152
+
153
  }
154
  }
155
  .note
198
  .table
199
  {
200
  //flex-wrap: wrap;
201
+ // table-layout: fixed;
202
+ display: flex;
203
+ //grid-template-columns: 3fr 2fr 2fr 4fr 2fr 2fr; // 120px 95px 95px repeat(3, 2fr);
204
+ // grid-template-rows: 50px;
205
+ // grid-gap: 1rem;
206
+ flex-direction: column;
207
  border-spacing: 10px 0;
208
  border: 1px solid #eee;
209
  word-wrap: normal;
210
  white-space: nowrap;
211
 
212
  .header, .row {
 
 
213
 
214
+ display: flex;
215
+
216
+
217
+ input.image_sizes_pname { max-width: 110px; }
218
+ input.image_sizes_name {
219
+ font-size: 10px;
220
+ border: 0;
221
+ background: unset;
222
+ margin: 0;
223
+ padding: 0;
224
+ }
225
+
226
+ span {
227
+ // display: inline-block;
228
+ padding: 5px;
229
+ //min-width: 100px;
230
+ flex-basis: 100px;
231
+ &:nth-of-type(1)
232
+ {
233
+ flex-basis: 120px;
234
+ }
235
+ &:nth-of-type(4)
236
+ {
237
+ flex-basis: 150px;
238
+ }
239
+ button
240
+ {
241
+ padding: 0;
242
+ background: unset;
243
+ border: 0;
244
+ box-shadow: none;
245
+ span { color: #ff0000; }
246
+ }
247
  //min-width: 100px;
248
  }
249
  }
303
  {
304
  display: flex;
305
  flex: 1;
306
+ .note { flex: 2; display: inline-block; }
307
+ }
308
+ @include breakpoint(0,1500px)
309
+ {
310
+ .option
311
+ {
312
+ flex-wrap:wrap;
313
+ label { width: 100%; }
314
+ .note { width: 100%; margin: 4px 0; }
315
+ }
316
  }
317
  }
318
 
393
  opacity: 100;
394
  }
395
 
396
+ .rta-ad
397
+ {
398
+ background: #fff;
399
+ border: 1px solid #eee;
400
+ padding: 16px;
401
+ margin: 20px 0;
402
+ display: flex;
403
+ align-items: center;
404
+ .img-wrapper {
405
+ // float: left;
406
+ margin-right: 25px;
407
+ }
408
+ h3, p { margin: 6px 0; }
409
+ a {
410
+ font-size: 16px;
411
+ font-weight: 700;
412
+ text-decoration: underline;
413
+ }
414
+
415
+ }
416
+
417
 
418
  } // class rta-admin
templates/admin/load_media_upload_js.php DELETED
@@ -1,31 +0,0 @@
1
- <script language="javascript">
2
- jQuery(document).ready(function($){
3
- var mediaUploader;
4
- $('.upload_media_button').unbind( 'click' );
5
- $('.upload_media_button').click(function(e) {
6
- var url_obj = $(this).attr("data-obj-url");
7
- var id_obj = $(this).attr("data-obj-id");
8
- e.preventDefault();
9
- // If the uploader object has already been created, reopen the dialog
10
- if (mediaUploader) {
11
- mediaUploader.open();
12
- return;
13
- }
14
- // Extend the wp.media object
15
- mediaUploader = wp.media.frames.file_frame = wp.media({
16
- title: 'Choose Media',
17
- button: {text: 'Choose Media'},
18
- multiple: false
19
- });
20
-
21
- // When a file is selected, grab the URL and set it as the text field's value
22
- mediaUploader.on('select', function() {
23
- var attachment = mediaUploader.state().get('selection').first().toJSON();
24
- $('#'+url_obj).val(attachment.url);
25
- $('#'+id_obj).val(attachment.id);
26
- });
27
- // Open the uploader dialog
28
- mediaUploader.open();
29
- });
30
- });
31
- </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/admin/rta_generate_thumbnails.php CHANGED
@@ -1,20 +1,24 @@
 
 
 
 
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'>
12
  <h2><?php _e('Settings', 'regenerate-thumbnails-advanced'); ?></h2>
13
- <?php $view->loadChildTemplate('view_rta_settings'); ?>
14
  </div>
15
  </div>
16
-
17
- <?php $view->loadChildTemplate('view_regenerate_process'); ?>
18
  </div> <!-- rta admin wrap. -->
19
 
20
  </div>
1
+ <?php
2
+ namespace ReThumbAdvanced;
3
+ ?>
4
+
5
  <div class='wrap'> <!-- this wrap to keep notices and other scum out of the interface -->
6
  <h1><?php _e('Regenerate Thumbnails Advanced','regenerate-thumbnails-advanced'); ?></h1>
7
 
8
  <div class="rta-admin-wrap rta-admin wrap">
9
 
10
+ <div class='two-panel-wrap settings-panels'>
11
  <div class='rta-regenerate-wrap'>
12
  <h2><?php _e('Regenerate Options', 'regenerate-thumbnails-advanced') ?></h2>
13
+ <?php $this->loadChildTemplate('view_rta_regenerate'); ?>
14
  </div>
15
  <div class='rta-settings-wrap'>
16
  <h2><?php _e('Settings', 'regenerate-thumbnails-advanced'); ?></h2>
17
+ <?php $this->loadChildTemplate('view_rta_settings'); ?>
18
  </div>
19
  </div>
20
+ <?php $this->loadChildTemplate('view_ad'); ?>
21
+ <?php $this->loadChildTemplate('view_regenerate_process'); ?>
22
  </div> <!-- rta admin wrap. -->
23
 
24
  </div>
templates/admin/rta_image_sizes.php DELETED
@@ -1,84 +0,0 @@
1
- <?php if ( $message!="" ) { echo $message; }?>
2
- <div class="wrap">
3
- <h2>Manage Image Sizes</h2>
4
- <table class="wp-list-table widefat fixed" cellspacing="0">
5
- <thead>
6
- <tr>
7
- <th scope="col" class="manage-column" style="">Manage Image Sizes</th>
8
- </tr>
9
- </thead>
10
- <tbody id="the-list">
11
- <tr>
12
- <td>
13
- <form method="post" name="frm_rta_image_sizes" id="frm_rta_image_sizes" class="frm_rta" action="?page=rta_image_sizes" enctype="multipart/form-data">
14
- <table width="100%">
15
- <tr>
16
- <td width="100">Image Sizes</td>
17
- <td>
18
- <input type="button" name="btn_add_image_size" id="btn_add_image_size" class="btn_add_more" value="Add New Size" onclick="javascript:rta_add_image_size_row();" />
19
- <p></p>
20
- <table width="100%" id="rta_add_image_size_container">
21
- <tr>
22
- <td colspan="6"></td>
23
- </tr>
24
- <?php
25
- if(sizeof($image_sizes['name'])>0){ ?>
26
- <tr id="rta_add_images_header">
27
- <td width="20%"><b>Image Size Public Name</b></td>
28
- <td width="15%"><b>Max. Width</b></td>
29
- <td width="15%"><b>Max. Height</b></td>
30
- <td width="15%"><b>Cropping</b></td>
31
- <td width="20%"><b>Image Size Name</b></td>
32
- <td width="15%"></td>
33
- </tr>
34
- <?php
35
- for($i=0;$i<sizeof($image_sizes['name']);$i++){ ?>
36
- <?php $rowid = uniqid();?>
37
- <tr id="<?php echo $rowid;?>">
38
- <td>
39
- <input type="text" name="image_sizes[pname][]" class="image_sizes_pname" value="<?php echo $image_sizes['pname'][$i];?>" placeholder="Image Size Public Name" onblur="javascript: rta_image_name_changed(this,'<?php echo $rowid;?>');"/>
40
- </td>
41
- <td>
42
- <input type="number" name="image_sizes[width][]" class="image_sizes_width" value="<?php echo $image_sizes['width'][$i];?>" placeholder="Image Size Width" onchange="javascript: rta_image_width_changed(this,'<?php echo $rowid;?>');"/>
43
- </td>
44
- <td>
45
- <input type="number" name="image_sizes[height][]" class="image_sizes_height" value="<?php echo $image_sizes['height'][$i];?>" placeholder="Image Size Height" onchange="javascript: rta_image_height_changed(this,'<?php echo $rowid;?>');"/>
46
- </td>
47
- <td>
48
- <select name="image_sizes[cropping][]" class="image_sizes_cropping" onchange="javascript: rta_image_crop_changed(this,'<?php echo $rowid;?>');">
49
- <option value="no_cropped"<?php if($image_sizes['cropping'][$i]=='no_cropped'){echo ' selected';}?>>No</option>
50
- <option value="cropped"<?php if($image_sizes['cropping'][$i]=='cropped'){echo ' selected';}?>>Yes</option>
51
- <option value="left_top"<?php if($image_sizes['cropping'][$i]=='left_top'){echo ' selected';}?>>Left top</option>
52
- <option value="left_center"<?php if($image_sizes['cropping'][$i]=='left_center'){echo ' selected';}?>>Left center</option>
53
- <option value="left_bottom"<?php if($image_sizes['cropping'][$i]=='left_bottom'){echo ' selected';}?>>Left bottom</option>
54
- <option value="center_top"<?php if($image_sizes['cropping'][$i]=='center_top'){echo ' selected';}?>>Center top</option>
55
- <option value="center_center"<?php if($image_sizes['cropping'][$i]=='center_center'){echo ' selected';}?>>Center center</option>
56
- <option value="center_bottom"<?php if($image_sizes['cropping'][$i]=='center_bottom'){echo ' selected';}?>>Center bottom</option>
57
- <option value="right_top"<?php if($image_sizes['cropping'][$i]=='right_top'){echo ' selected';}?>>Right top</option>
58
- <option value="right_center"<?php if($image_sizes['cropping'][$i]=='right_center'){echo ' selected';}?>>Right center</option>
59
- <option value="right_bottom"<?php if($image_sizes['cropping'][$i]=='right_bottom'){echo ' selected';}?>>Right bottom</option>
60
- </select>
61
- </td>
62
- <td>
63
- <input type="text" readonly name="image_sizes[name][]" class="image_sizes_name" value="<?php echo $image_sizes['name'][$i];?>" placeholder="Image Size name" />
64
- </td>
65
- <td>
66
- <input type="button" name="btn_remove_image_size_row" value="<?php _e('','regenerate-thumbnails-advanced'); ?>Remove" class="btn_remove_row" onclick="javascript:rta_remove_image_size_row('<?php echo $rowid;?>');" />
67
- </td>
68
- </tr>
69
- <?php }}?>
70
- </table>
71
- </td>
72
- </tr>
73
- <tr>
74
- <td></td>
75
- <td><input type="submit" name="btnsave" id="btnsave" value="<?php echo $rta_lang['btn_update'];?>" class="button button-primary">
76
- </td>
77
- </tr>
78
- </table>
79
- </form>
80
- </td>
81
- </tr>
82
- </tbody>
83
- </table>
84
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/admin/settings.php DELETED
@@ -1,41 +0,0 @@
1
- <?php if ( $message!="" ) { echo $message; }?>
2
- <div class="wrap">
3
- <h2><?php echo $rta_lang['settings'];?></h2>
4
- <table class="wp-list-table widefat fixed" cellspacing="0">
5
- <thead>
6
- <tr>
7
- <th scope="col" class="manage-column" style=""><?php echo $rta_lang['misc_settings'];?></th>
8
- </tr>
9
- </thead>
10
- <tbody id="the-list">
11
- <tr>
12
- <td>
13
- <form method="post" name="frm_rta" id="frm_rta" class="frm_rta" action="?page=rta_settings" enctype="multipart/form-data">
14
- <table width="100%">
15
- <tr>
16
- <td width="180"><?php echo $rta_lang['txt_field_label'];?></td>
17
- <td>
18
- <input type="text" name="textfield" id="textfield" value="<?php echo $textfield;?>" />
19
- </td>
20
- </tr>
21
- <tr>
22
- <td><?php echo $rta_lang['upload_field_label'];?></td>
23
- <td>
24
- <input type="text" name="upload_field_url" id="upload_field_url" value="<?php echo $upload_field_url;?>" class="textfield" />
25
- <input type="hidden" name="upload_field" id="upload_field" value="<?php echo $upload_field;?>" />
26
- <input class="upload_media_button button" type="button" name="btnupload" value="<?php echo $rta_lang['btn_upload'];?>" data-obj-url="upload_field_url" data-obj-id="upload_field" />
27
- </td>
28
- </tr>
29
-
30
- <tr>
31
- <td></td>
32
- <td><input type="submit" name="btnsave" id="btnsave" value="<?php echo $rta_lang['btn_update'];?>" class="button button-primary">
33
- </td>
34
- </tr>
35
- </table>
36
- </form>
37
- </td>
38
- </tr>
39
- </tbody>
40
- </table>
41
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
templates/admin/view_ad.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace ReThumbAdvanced;
3
+ ?>
4
+
5
+ <section class='rta-ad'>
6
+
7
+ <div class='img-wrapper'><img src="<?php echo $this->getURL('images/robo-winky.png') ?>"></div>
8
+ <div class='text-wrapper'>
9
+ <p><?php _e('ARE YOU CONCERNED WITH YOUR SITE SPEED? Allow ShortPixel specialists to find the solution for you.', 'regenerate-thumbnails-advanced'); ?> </p>
10
+ <p><a href="https://shortpixel.com/lp/wso/?utm_source=RTA" target="_blank"><?php _e('Find Out More', 'regenerate-thumbnails-advanced'); ?></a></p>
11
+ </div>
12
+ </section>
templates/admin/view_regenerate_process.php CHANGED
@@ -1,10 +1,13 @@
 
 
 
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'>
@@ -26,11 +29,12 @@
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>
@@ -38,21 +42,17 @@
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();
53
  $spInstalled = isset($plugins['shortpixel-image-optimiser/wp-shortpixel.php']);
54
  $spActive = is_plugin_active('shortpixel-image-optimiser/wp-shortpixel.php');
55
-
56
  ?>
57
 
58
  <div class='rta_success_box rta_hidden'>
@@ -64,31 +64,31 @@
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>
1
+ <?php
2
+ namespace ReThumbAdvanced;
3
+ ?>
4
 
5
  <section class='regenerate rta_hidden'>
6
  <div class='container two-panel-wrap'>
7
 
8
  <div class="rta_progress two-panel-wrap">
9
  <div class="images rta_thumbnail_view rta_panel_off">
10
+ <h4 class='thumb-label'><?php _e('Last Regenerated Image:','regenerate-thumbnails-advanced'); ?></h4>
11
  <div class='thumbnail'> <img src="" alt=""> </div>
12
  </div>
13
  <div class='rta_progress_view rta_panel_off'>
29
  <text class="CircularProgressbar-text" x="50" y="50">0%</text>
30
  <text class="progress-count" x="50" y="70"><tspan class='current'>0</tspan> / <tspan class='total'>0</tspan></text>
31
  </svg>
 
32
  </div>
33
  </div>
34
 
35
  <div class="rta_status_box">
36
+ <button class='button stop-process' disabled><?php _e('Stop Process', 'regenerate-thumbnails-advanced') ?></button>
37
+
38
  <div class="rta_notices rta_panel_off">
39
  <ul class="statuslist">
40
  </ul>
42
  <div class="rta_wait_loader rta_panel_off" >
43
  <span class='dashicons dashicons-update'>&nbsp;</span>
44
  <div>
45
+ <h4><?php _e('Starting Process', 'regenerate-thumbnails-advanced', 'regenerate-thumbnails-advanced'); ?></h4>
46
+ <?php _e('Please wait...','regenerate-thumbnails-advanced', 'regenerate-thumbnails-advanced'); ?>
47
  </div>
48
  </div>
49
 
50
  </div>
51
 
 
 
52
  <?php
 
53
  $plugins = get_plugins();
54
  $spInstalled = isset($plugins['shortpixel-image-optimiser/wp-shortpixel.php']);
55
  $spActive = is_plugin_active('shortpixel-image-optimiser/wp-shortpixel.php');
 
56
  ?>
57
 
58
  <div class='rta_success_box rta_hidden'>
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!", 'regenerate-thumbnails-advanced'); ?>
68
  </a>
69
  </h3>
70
+ <div>
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 Regenerate Thumbnails Advanced user! Forever!", 'regenerate-thumbnails-advanced'); ?>
77
  </p>
78
+ <div><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", 'regenerate-thumbnails-advanced'); ?>
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>', 'regenerate-thumbnails-advanced'), '<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.', 'regenerate-thumbnails-advanced'), '<a href="' . $activate_url . '">', '</a>'); ?></strong></p>
92
  <?php endif; ?>
93
  </div>
94
  </div>
templates/admin/view_rta_regenerate.php CHANGED
@@ -1,4 +1,6 @@
1
-
 
 
2
 
3
  <form method="post" name="rtaform_process" id="rtaform_process" class="frm_rta" enctype="multipart/form-data">
4
  <section class='period'>
@@ -54,6 +56,8 @@
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>
@@ -70,13 +74,15 @@
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>
1
+ <?php
2
+ namespace ReThumbAdvanced;
3
+ ?>
4
 
5
  <form method="post" name="rtaform_process" id="rtaform_process" class="frm_rta" enctype="multipart/form-data">
6
  <section class='period'>
56
  </div>
57
  <div class='warning inline rta-notice rta_hidden' id='warn-delete-items'>
58
  <div class='icon dashicons-info dashicons'></div>
59
+
60
+
61
  <p><?php _e('Not selected thumbnails will be removed from your site. Check your settings if this is intentional.'); ?></p>
62
 
63
  <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>
74
  </div>
75
  </div>
76
 
77
+ <a href="https://help.shortpixel.com/article/233-quick-guide-to-using-regenerate-thumbnails-advanced-settings" target="_blank">
78
+ <span class="dashicons dashicons-editor-help"></span>Read more</a>
79
  </div>
80
  </div> <!-- container -->
81
  </section>
82
 
83
  <section class='form_controls'>
84
  <div class='container'>
85
+ <button type='submit' disabled class='rta_regenerate disabled'><span class='dashicons dashicons-controls-play'>&nbsp;</span> <?php _e('Regenerate', 'regenerate-thumbnails-advanced'); ?></button>
86
  <p class='save_note rta_hidden'><?php _e('Save your settings first','regenerate-thumbnails-advanced'); ?></p>
87
  </div>
88
  </section>
templates/admin/view_rta_settings.php CHANGED
@@ -1,3 +1,6 @@
 
 
 
1
 
2
  <form method="POST" name="rta_settings_form" id="rta_settings_form" enctype="multipart/form-data">
3
  <section class='image_sizes'>
@@ -10,15 +13,15 @@
10
  $headershow = (count($image_sizes) == 0) ? ' rta_hidden' : '';
11
  ?>
12
 
13
- <div class='header flex <?php echo $headershow ?>'>
14
 
15
- <span><b><?php _e('Image Size Public Name','regenerate-thumbnails-advanced'); ?></b></span>
16
  <span><b><?php _e('Max. Width','regenerate-thumbnails-advanced'); ?></b></span>
17
  <span><b><?php _e('Max. Height','regenerate-thumbnails-advanced'); ?></b></span>
18
  <span><b><?php _e('Cropping','regenerate-thumbnails-advanced'); ?></b></span>
19
  <span><b><?php _e('Image Size Name','regenerate-thumbnails-advanced'); ?></b></span>
20
  <span>&nbsp;</span>
21
- </div>
22
 
23
  <?php
24
  if (isset($image_sizes['name'])){
@@ -28,40 +31,42 @@
28
  $rowid = uniqid();
29
 
30
  ?>
31
- <div id="<?php echo $rowid;?>" class='row'>
32
 
33
- <span><input type="text" name="image_sizes[pname][]" class="image_sizes_pname" value="<?php echo $image_sizes['pname'][$i];?>" placeholder="<?php _e('Image Size Public Name','regenerate-thumbnails-advanced'); ?>" /></span>
34
 
35
  <span><input type="number" min="0" name="image_sizes[width][]" class="image_sizes_width tiny" value="<?php echo $image_sizes['width'][$i];?>" placeholder="<?php _e('Width','regenerate-thumbnails-advanced'); ?>" /> px </span>
36
 
37
  <span> <input type="number" min="0" name="image_sizes[height][]" class="image_sizes_height tiny" value="<?php echo $image_sizes['height'][$i];?>" placeholder="<?php _e('Height','regenerate-thumbnails-advanced'); ?>" /> px </span>
38
 
39
  <span> <select name="image_sizes[cropping][]" class="image_sizes_cropping">
40
- <?php echo $view->cropOptions($image_sizes['cropping'][$i]); ?>
41
  </select>
42
  </span>
43
 
44
- <span>
45
  <input type="text" readonly name="image_sizes[name][]" class="image_sizes_name" value="<?php echo $image_sizes['name'][$i];?>" placeholder="<?php _e('Image Size name','regenerate-thumbnails-advanced'); ?>" />
 
46
  </span>
47
  <span>
48
- <input type="button" name="btn_remove_image_size_row" value="<?php _e('Remove','regenerate-thumbnails-advanced'); ?>" class="btn_remove_row" />
49
  </span>
50
- </div> <!-- row -->
51
  <?php }}?>
52
  <div class='row proto'>
53
- <span><input type="text" name="image_sizes[pname][]" class="image_sizes_pname" value="" placeholder="<?php _e('Image Size Public Name','regenerate-thumbnails-advanced'); ?>" /></span>
54
  <span><input type="number" name="image_sizes[width][]" class="image_sizes_width tiny" value="" placeholder="<?php _e('Width','regenerate-thumbnails-advanced'); ?>" /> px </span>
55
  <span> <input type="number" name="image_sizes[height][]" class="image_sizes_height tiny" value="" placeholder="<?php _e('Height','regenerate-thumbnails-advanced'); ?>" /> px </span>
56
  <span><select name="image_sizes[cropping][]" class="image_sizes_cropping">
57
- <?php echo $view->cropOptions(); ?>
58
  </select>
59
  </span>
60
  <span>
61
- <input type="text" readonly name="image_sizes[name][]" class="image_sizes_name" value="" placeholder="<?php _e('Image Size name','regenerate-thumbnails-advanced'); ?>" />
62
  </span>
63
  <span>
64
- <input type="button" name="btn_remove_image_size_row" value="<?php _e('Remove','regenerate-thumbnails-advanced'); ?>" class="btn_remove_row" />
 
65
  </span>
66
  </div> <!-- row -->
67
  </div> <!-- table -->
@@ -75,7 +80,7 @@
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>
80
  <div class='select-options'><span class='select' data-action='select' data-target='regenerate_sizes'><?php _e('Select All', 'regenerate-thumbnails-advanced'); ?></span>
81
  <span class='deselect' data-action='deselect' data-target='regenerate_sizes'><?php _e('Deselect All', 'regenerate-thumbnails-advanced'); ?></span>
1
+ <?php
2
+ namespace ReThumbAdvanced;
3
+ ?>
4
 
5
  <form method="POST" name="rta_settings_form" id="rta_settings_form" enctype="multipart/form-data">
6
  <section class='image_sizes'>
13
  $headershow = (count($image_sizes) == 0) ? ' rta_hidden' : '';
14
  ?>
15
 
16
+ <div class='header <?php echo $headershow ?>'>
17
 
18
+ <span><b><?php _e('Public Name','regenerate-thumbnails-advanced'); ?></b></span>
19
  <span><b><?php _e('Max. Width','regenerate-thumbnails-advanced'); ?></b></span>
20
  <span><b><?php _e('Max. Height','regenerate-thumbnails-advanced'); ?></b></span>
21
  <span><b><?php _e('Cropping','regenerate-thumbnails-advanced'); ?></b></span>
22
  <span><b><?php _e('Image Size Name','regenerate-thumbnails-advanced'); ?></b></span>
23
  <span>&nbsp;</span>
24
+ </div>
25
 
26
  <?php
27
  if (isset($image_sizes['name'])){
31
  $rowid = uniqid();
32
 
33
  ?>
34
+ <div id="<?php echo $rowid;?>" class='row'>
35
 
36
+ <span><input type="text" name="image_sizes[pname][]" class="image_sizes_pname" value="<?php echo $image_sizes['pname'][$i];?>" placeholder="<?php _e('Name','regenerate-thumbnails-advanced'); ?>" /></span>
37
 
38
  <span><input type="number" min="0" name="image_sizes[width][]" class="image_sizes_width tiny" value="<?php echo $image_sizes['width'][$i];?>" placeholder="<?php _e('Width','regenerate-thumbnails-advanced'); ?>" /> px </span>
39
 
40
  <span> <input type="number" min="0" name="image_sizes[height][]" class="image_sizes_height tiny" value="<?php echo $image_sizes['height'][$i];?>" placeholder="<?php _e('Height','regenerate-thumbnails-advanced'); ?>" /> px </span>
41
 
42
  <span> <select name="image_sizes[cropping][]" class="image_sizes_cropping">
43
+ <?php echo $this->cropOptions($image_sizes['cropping'][$i]); ?>
44
  </select>
45
  </span>
46
 
47
+ <span >
48
  <input type="text" readonly name="image_sizes[name][]" class="image_sizes_name" value="<?php echo $image_sizes['name'][$i];?>" placeholder="<?php _e('Image Size name','regenerate-thumbnails-advanced'); ?>" />
49
+
50
  </span>
51
  <span>
52
+ <button class="btn_remove_row" type="button" name="btn_remove_image_size_row"><span class='dashicons dashicons-no'>&nbsp;</span></button>
53
  </span>
54
+ </div> <!-- row -->
55
  <?php }}?>
56
  <div class='row proto'>
57
+ <span><input type="text" name="image_sizes[pname][]" class="image_sizes_pname" value="" placeholder="<?php _e('Name','regenerate-thumbnails-advanced'); ?>" /></span>
58
  <span><input type="number" name="image_sizes[width][]" class="image_sizes_width tiny" value="" placeholder="<?php _e('Width','regenerate-thumbnails-advanced'); ?>" /> px </span>
59
  <span> <input type="number" name="image_sizes[height][]" class="image_sizes_height tiny" value="" placeholder="<?php _e('Height','regenerate-thumbnails-advanced'); ?>" /> px </span>
60
  <span><select name="image_sizes[cropping][]" class="image_sizes_cropping">
61
+ <?php echo $this->cropOptions(); ?>
62
  </select>
63
  </span>
64
  <span>
65
+ <input type="text" readonly name="image_sizes[name][]" class="image_sizes_name" value="" placeholder="<?php _e('Image Size name','regenerate-thumbnails-advanced'); ?>" />
66
  </span>
67
  <span>
68
+ <button class="btn_remove_row" type="button" name="btn_remove_image_size_row"><span class='dashicons dashicons-no'>&nbsp;</span></button>
69
+
70
  </span>
71
  </div> <!-- row -->
72
  </div> <!-- table -->
80
  <div class='option'>
81
  <label><?php _e('Regenerate these thumbnails:', 'regenerate-thumbnails-advanced') ?></label>
82
  <div class='checkbox-list'>
83
+ <?php echo $this->generateImageSizeOptions($view->process_image_sizes); ?>
84
  </div>
85
  <div class='select-options'><span class='select' data-action='select' data-target='regenerate_sizes'><?php _e('Select All', 'regenerate-thumbnails-advanced'); ?></span>
86
  <span class='deselect' data-action='deselect' data-target='regenerate_sizes'><?php _e('Deselect All', 'regenerate-thumbnails-advanced'); ?></span>
templates/common/error.php DELETED
@@ -1,3 +0,0 @@
1
- <div id="<?php echo $type;?>" class="updated fade rta_alert_box rta_alert_<?php echo $type;?>">
2
- <?php echo $message;?>
3
- </div>
 
 
 
templates/common/message.php DELETED
@@ -1,3 +0,0 @@
1
- <div id="<?php echo $type;?>" class="updated fade rta_alert_box rta_alert_<?php echo $type;?>">
2
- <?php echo $message;?>
3
- </div>
 
 
 
templates/common/warning.php DELETED
@@ -1,3 +0,0 @@
1
- <div id="<?php echo $type;?>" class="updated fade rta_alert_box rta_alert_<?php echo $type;?>">
2
- <?php echo $message;?>
3
- </div>