ShortPixel Image Optimizer - Version 5.0.5

Version Description

Release date July 7th, 2022 * Fix: in some cases the legacy optimization data was not migrated properly, resulting in backup-related errors; * Fix: added the possibility to redo the migration of the optimization data when the backups exist; * Fix: significantly reduced the number of queries when WP Offload Media is in use, as this was causing slowness in some cases; * Fix: the automatic processing now works correctly when using the block editor as well as on other pages where it was broken; * Fix: the unlisted thumbnails were not processed correctly and showed up as not optimized; * Fix: the integration with the Photo Engine and WP/LR Sync plugins works properly again; * Fix: the filter in the Media Library was making the image name go away; * Fix: changing the API Key now resets correctly the credits information; * Fix: removed a persistent notification about a potential insufficient quota; * Fix: the "Optimize now" button works correctly in Custom Media; * Fix: the "Extend quota" button works correctly in the Media Library; * Fix: other folders from the wp-content/uplods folder can now be added as Custom Media folders; * Fix: the size exclusions were not working as expected for thumbnails; * Fix: updated various pieces of code in accordance with the WordPress Coding Standards; * Tweak: the wait time between checking if there is anything to optimize has been lowered; * Tweak: added a clear function for WP-CLI, to clear the existing queue(s); * Language: 3 new string added, 0 updated, 0 fuzzed, and 7 obsoleted.

Download this release

Release Info

Developer petredobrescu
Plugin Icon 128x128 ShortPixel Image Optimizer
Version 5.0.5
Comparing to
See all releases

Code changes from version 5.0.4 to 5.0.5

Files changed (72) hide show
  1. build/shortpixel/log/src/ShortPixelLogger.php +3 -0
  2. build/shortpixel/log/src/view-debug-box.php +2 -2
  3. build/shortpixel/notices/src/NoticeController.php +18 -8
  4. class/Controller.php +3 -0
  5. class/Controller/AdminNoticesController.php +7 -56
  6. class/Controller/AjaxController.php +53 -22
  7. class/Controller/ApiKeyController.php +5 -0
  8. class/Controller/BulkController.php +2 -1
  9. class/Controller/FileSystemController.php +23 -0
  10. class/Controller/FrontController.php +3 -18
  11. class/Controller/OptimizeController.php +0 -4
  12. class/Controller/OtherMediaController.php +33 -13
  13. class/Controller/Queue/Queue.php +2 -2
  14. class/Controller/QuotaController.php +5 -5
  15. class/Controller/SettingsController.php +8 -20
  16. class/Controller/View/BulkRestoreAll.php +0 -90
  17. class/Controller/View/EditMediaViewController.php +2 -6
  18. class/Controller/View/ListMediaViewController.php +7 -8
  19. class/Controller/View/OtherMediaViewController.php +28 -17
  20. class/Helper/InstallHelper.php +6 -5
  21. class/Helper/UiHelper.php +39 -10
  22. class/Model/ApiKeyModel.php +1 -1
  23. class/Model/EnvironmentModel.php +8 -3
  24. class/Model/File/DirectoryModel.php +3 -2
  25. class/Model/File/FileModel.php +4 -2
  26. class/Model/Image/ImageModel.php +4 -3
  27. class/Model/Image/MediaLibraryModel.php +145 -79
  28. class/Model/Image/MediaLibraryThumbnailModel.php +18 -4
  29. class/ViewController.php +6 -4
  30. class/external/cloudflare.php +1 -2
  31. class/external/gravityforms.php +2 -1
  32. class/external/nextgen/nextGenController.php +11 -4
  33. class/external/spai.php +3 -1
  34. class/external/wp-cli/wp-cli-base.php +29 -1
  35. class/external/wp-offload-media.php +89 -19
  36. class/view/bulk/part-bulk-special.php +24 -24
  37. class/view/bulk/part-dashboard.php +14 -27
  38. class/view/bulk/part-finished.php +17 -19
  39. class/view/bulk/part-process.php +33 -37
  40. class/view/bulk/part-progressbar.php +4 -4
  41. class/view/bulk/part-selection.php +35 -34
  42. class/view/bulk/part-summary.php +44 -33
  43. class/view/settings/part-advanced.php +126 -93
  44. class/view/settings/part-cloudflare.php +23 -22
  45. class/view/settings/part-debug.php +33 -23
  46. class/view/settings/part-general.php +71 -76
  47. class/view/settings/part-nokey.php +26 -27
  48. class/view/settings/part-optpie.php +4 -6
  49. class/view/settings/part-statistics.php +0 -138
  50. class/view/settings/part-tools.php +25 -25
  51. class/view/settings/part-wso.php +0 -28
  52. class/view/shortpixel-feedback.php +10 -10
  53. class/view/shortpixel-plugin-request.php +2 -2
  54. class/view/snippets/part-comparer.php +1 -1
  55. class/view/snippets/part-inline-help.php +4 -0
  56. class/view/snippets/part-inline-modal.php +4 -0
  57. class/view/snippets/part-svgloader.php +5 -0
  58. class/view/view-bulk.php +5 -9
  59. class/view/view-edit-media.php +6 -10
  60. class/view/view-list-media.php +5 -7
  61. class/view/view-other-media.php +24 -23
  62. class/view/view-restore-all.php +0 -53
  63. class/view/view-settings.php +10 -13
  64. class/wp-shortpixel-settings.php +4 -33
  65. readme.txt +21 -1
  66. res/js/picturefill.min.js +0 -5
  67. res/js/screens/screen-bulk.js +13 -8
  68. res/js/screens/screen-media.js +18 -1
  69. res/js/shortpixel-processor.js +10 -4
  70. res/js/shortpixel-worker.js +1 -1
  71. shortpixel-plugin.php +468 -509
  72. wp-shortpixel.php +5 -5
build/shortpixel/log/src/ShortPixelLogger.php CHANGED
@@ -49,16 +49,19 @@ namespace ShortPixel\ShortPixelLogger;
49
  $ns = __NAMESPACE__;
50
  $this->namespace = substr($ns, 0, strpos($ns, '\\')); // try to get first part of namespace
51
 
 
52
  if (isset($_REQUEST['SHORTPIXEL_DEBUG'])) // manual takes precedence over constants
53
  {
54
  $this->is_manual_request = true;
55
  $this->is_active = true;
56
 
 
57
  if ($_REQUEST['SHORTPIXEL_DEBUG'] === 'true')
58
  {
59
  $this->logLevel = DebugItem::LEVEL_INFO;
60
  }
61
  else {
 
62
  $this->logLevel = intval($_REQUEST['SHORTPIXEL_DEBUG']);
63
  }
64
 
49
  $ns = __NAMESPACE__;
50
  $this->namespace = substr($ns, 0, strpos($ns, '\\')); // try to get first part of namespace
51
 
52
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is not a form
53
  if (isset($_REQUEST['SHORTPIXEL_DEBUG'])) // manual takes precedence over constants
54
  {
55
  $this->is_manual_request = true;
56
  $this->is_active = true;
57
 
58
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is not a form
59
  if ($_REQUEST['SHORTPIXEL_DEBUG'] === 'true')
60
  {
61
  $this->logLevel = DebugItem::LEVEL_INFO;
62
  }
63
  else {
64
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is not a form
65
  $this->logLevel = intval($_REQUEST['SHORTPIXEL_DEBUG']);
66
  }
67
 
build/shortpixel/log/src/view-debug-box.php CHANGED
@@ -49,8 +49,8 @@ wp_enqueue_script( 'jquery-ui-draggable' );
49
 
50
 
51
  <div class='sp_debug_box'>
52
- <div class='header'><?php echo $view->namespace ?> Debug Box </div>
53
- <a target="_blank" href='<?php echo $view->logLink ?>'>Logfile</a>
54
  <div class='content_box'>
55
 
56
  </div>
49
 
50
 
51
  <div class='sp_debug_box'>
52
+ <div class='header'><?php echo esc_html($view->namespace) ?> Debug Box </div>
53
+ <a target="_blank" href='<?php echo esc_url($view->logLink) ?>'>Logfile</a>
54
  <div class='content_box'>
55
 
56
  </div>
build/shortpixel/notices/src/NoticeController.php CHANGED
@@ -212,14 +212,23 @@ class NoticeController //extends ShortPixelController
212
  {
213
  $response = array('result' => false, 'reason' => '');
214
 
215
- if ( wp_verify_nonce( $_POST['nonce'], 'dismiss') )
216
  {
217
- if ($_POST['plugin_action'] == 'dismiss')
218
  {
219
- $id = sanitize_text_field($_POST['id']);
220
- $notice = $this->getNoticeByID($id);
221
-
222
- if($notice)
 
 
 
 
 
 
 
 
 
223
  {
224
  $notice->dismiss();
225
  $this->update();
@@ -228,7 +237,8 @@ class NoticeController //extends ShortPixelController
228
  else
229
  {
230
  Log::addError('Notice not found when dismissing -> ' . $id, self::$notices);
231
- $response['result'] = ' Notice ' . $id . ' not found. ';
 
232
  }
233
 
234
  }
@@ -349,7 +359,7 @@ class NoticeController //extends ShortPixelController
349
  {
350
  if (file_exists(__DIR__ . '/css/notices.css'))
351
  {
352
- echo '<style>' . file_get_contents(__DIR__ . '/css/notices.css') . '</style>';
353
  }
354
  else {
355
  Log::addDebug('Notices : css/notices.css could not be loaded');
212
  {
213
  $response = array('result' => false, 'reason' => '');
214
 
215
+ if (isset($_POST['nonce']) && wp_verify_nonce( sanitize_key($_POST['nonce']), 'dismiss') )
216
  {
217
+ if (isset($_POST['plugin_action']) && 'dismiss' == $_POST['plugin_action'] )
218
  {
219
+ $id = (isset($_POST['id'])) ? sanitize_text_field( wp_unslash($_POST['id'])) : null;
220
+
221
+ if (! is_null($id))
222
+ {
223
+
224
+ $notice = $this->getNoticeByID($id);
225
+ }
226
+ else
227
+ {
228
+ $notice = false;
229
+ }
230
+
231
+ if(false !== $notice)
232
  {
233
  $notice->dismiss();
234
  $this->update();
237
  else
238
  {
239
  Log::addError('Notice not found when dismissing -> ' . $id, self::$notices);
240
+ $response['result'] = false;
241
+ $response['reason'] = ' Notice ' . $id . ' not found. ';
242
  }
243
 
244
  }
359
  {
360
  if (file_exists(__DIR__ . '/css/notices.css'))
361
  {
362
+ echo '<style>' . esc_html(file_get_contents(__DIR__ . '/css/notices.css')) . '</style>';
363
  }
364
  else {
365
  Log::addDebug('Notices : css/notices.css could not be loaded');
class/Controller.php CHANGED
@@ -8,9 +8,11 @@ use ShortPixel\Helper\UiHelper as UiHelper;
8
  * So far none of the controller need or implement similar enough functions for a parent to make sense. * Perhaps this will change of time, so most are extending this parent.
9
  **/
10
 
 
11
  class Controller
12
  {
13
 
 
14
  protected $userIsAllowed = false;
15
 
16
  public function __construct()
@@ -18,6 +20,7 @@ class Controller
18
  $this->userIsAllowed = $this->checkUserPrivileges();
19
  }
20
 
 
21
  protected function checkUserPrivileges()
22
  {
23
  if ((current_user_can( 'manage_options' ) || current_user_can( 'upload_files' ) || current_user_can( 'edit_posts' )))
8
  * So far none of the controller need or implement similar enough functions for a parent to make sense. * Perhaps this will change of time, so most are extending this parent.
9
  **/
10
 
11
+ // @todo Think how to do this better.
12
  class Controller
13
  {
14
 
15
+ protected $model;
16
  protected $userIsAllowed = false;
17
 
18
  public function __construct()
20
  $this->userIsAllowed = $this->checkUserPrivileges();
21
  }
22
 
23
+
24
  protected function checkUserPrivileges()
25
  {
26
  if ((current_user_can( 'manage_options' ) || current_user_can( 'upload_files' ) || current_user_can( 'edit_posts' )))
class/Controller/AdminNoticesController.php CHANGED
@@ -28,6 +28,7 @@ class AdminNoticesController extends \ShortPixel\Controller
28
  //const MSG_NO_
29
  const MSG_QUOTA_REACHED = 'QuotaReached100';
30
  const MSG_UPGRADE_MONTH = 'UpgradeNotice200'; // When processing more than the subscription allows on average..
 
31
  const MSG_UPGRADE_BULK = 'UpgradeNotice201'; // when there is no enough for a bulk run.
32
 
33
  const MSG_NO_APIKEY = 'ApiNotice300'; // API Key not found
@@ -182,7 +183,6 @@ class AdminNoticesController extends \ShortPixel\Controller
182
  $this->doUnlistedNotices();
183
  $this->doQuotaNotices();
184
  $this->doIntegrationNotices();
185
- $this->doHelpOptInNotices();
186
  $this->doRemoteNotices();
187
 
188
  $this->doListViewNotice();
@@ -334,6 +334,7 @@ class AdminNoticesController extends \ShortPixel\Controller
334
  return; // no key, no quota.
335
  }
336
 
 
337
  if(isset($_GET['checkquota'])) {
338
  //$shortpixel->getQuotaInformation();
339
  $quota = $quotaController->getQuota();
@@ -351,30 +352,10 @@ class AdminNoticesController extends \ShortPixel\Controller
351
  $quotaController = QuotaController::getInstance();
352
  $quotaData = $quotaController->getQuota();
353
 
354
-
355
- $bulk_notice = $noticeController->getNoticeByID(self::MSG_UPGRADE_BULK);
356
- $bulk_is_dismissed = ($bulk_notice && $bulk_notice->isDismissed() ) ? true : false;
357
-
358
  $month_notice = $noticeController->getNoticeByID(self::MSG_UPGRADE_MONTH);
359
 
360
- //this is for bulk page - alert on the total credits for total images
361
- if(! $bulk_is_dismissed && $env->is_bulk_page && $this->bulkUpgradeNeeded()) {
362
-
363
- $todo = $statsControl->find('total', 'itemsTotal') + $statsControl->find('total', 'thumbsTotal');
364
- $available = $quotaController->getAvailableQuota();
365
- $data = array('filesTodo' => $todo,
366
- 'quotaAvailable' => $available);
367
-
368
- //looks like the user hasn't got enough credits to bulk process all media library
369
- if ($bulk_notice === false)
370
- {
371
- $message = $this->getBulkUpgradeMessage($data);
372
- $notice = Notices::addNormal($message);
373
- Notices::makePersistent($notice, self::MSG_UPGRADE_BULK, YEAR_IN_SECONDS, array($this, 'upgradeBulkCallback'));
374
- }
375
- }
376
  //consider the monthly plus 1/6 of the available one-time credits.
377
- elseif( $this->monthlyUpgradeNeeded($quotaData)) {
378
 
379
  if ($month_notice === false)
380
  {
@@ -403,19 +384,6 @@ class AdminNoticesController extends \ShortPixel\Controller
403
  }
404
 
405
 
406
- protected function doHelpOptInNotices()
407
- {
408
- return; // this is disabled pending review.
409
- $settings = \wpSPIO()->settings();
410
- $optin = $settings->helpscoutOptin;
411
-
412
- if ($optin == -1)
413
- {
414
- $message = $this->getHelpOptinMessage();
415
- Notices::addNormal($message);
416
- }
417
- }
418
-
419
  protected function doRemoteNotices()
420
  {
421
  $notices = $this->get_remote_notices();
@@ -484,6 +452,8 @@ class AdminNoticesController extends \ShortPixel\Controller
484
  }
485
  elseif ($viewMode !== "list")
486
  {
 
 
487
  $message = __('You can see ShortPixel Image Optimiser actions and data only via the list view. Switch to the list view to use the plugin via the media library', 'shortpixel-image-optimiser');
488
  $new_notice = Notices::addNormal($message);
489
  Notices::makePersistent($new_notice, self::MSG_LISTVIEW_ACTIVE, YEAR_IN_SECONDS);
@@ -704,30 +674,11 @@ class AdminNoticesController extends \ShortPixel\Controller
704
  if(is_wp_error( $proposal )) {
705
  $proposal = array('body' => __('Error. Could not contact ShortPixel server for proposal', 'shortpixel-image-optimiser'));
706
  }
707
- die($proposal['body']);
708
-
709
- }
710
-
711
- protected function getHelpOptinMessage()
712
- {
713
-
714
- //onclick='ShortPixel.optInHelp(0)'
715
- $message = __('ShortPixel needs to ask permission to load the help functionality');
716
- $message .= "<div><button type='button' id='sp-helpscout-disallow' class='button button-primary' >" . __('No, I don\'t need help', 'shortpixel-image-optimiser') . "</button> &nbsp;&nbsp;";
717
- $message .= "<button type='button' id='sp-helpscout-allow' class='button button-primary'>" . __('Yes, load the help widget', 'shortpixel-image-optimiser') . "</button></div>";
718
-
719
- $message .= "<p>" . __('ShortPixel uses third party services Helpscout and Quriobot to access our help easier. By giving permission you agree to opt-in and load these service on ShortPixel related pages', 'shortpixel-image-optimiser');
720
 
721
- $message .= "<script>window.addEventListener('load', function(){
722
- document.getElementById('sp-helpscout-allow').addEventListener('click', ShortPixel.optInHelp, {once: true} );
723
- document.getElementById('sp-helpscout-allow').toggleParam = 'on';
724
- document.getElementById('sp-helpscout-disallow').addEventListener('click', ShortPixel.optInHelp, {once: true} );
725
- document.getElementById('sp-helpscout-disallow').toggleParam = 'off';
726
- }); </script>";
727
- return $message;
728
  }
729
 
730
- private function get_remote_notices()
731
  {
732
  $transient_name = 'shortpixel_remote_notice';
733
  $transient_duration = DAY_IN_SECONDS;
28
  //const MSG_NO_
29
  const MSG_QUOTA_REACHED = 'QuotaReached100';
30
  const MSG_UPGRADE_MONTH = 'UpgradeNotice200'; // When processing more than the subscription allows on average..
31
+ // @todo This one has been removed for now. Cleanup later on the line
32
  const MSG_UPGRADE_BULK = 'UpgradeNotice201'; // when there is no enough for a bulk run.
33
 
34
  const MSG_NO_APIKEY = 'ApiNotice300'; // API Key not found
183
  $this->doUnlistedNotices();
184
  $this->doQuotaNotices();
185
  $this->doIntegrationNotices();
 
186
  $this->doRemoteNotices();
187
 
188
  $this->doListViewNotice();
334
  return; // no key, no quota.
335
  }
336
 
337
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is not a form
338
  if(isset($_GET['checkquota'])) {
339
  //$shortpixel->getQuotaInformation();
340
  $quota = $quotaController->getQuota();
352
  $quotaController = QuotaController::getInstance();
353
  $quotaData = $quotaController->getQuota();
354
 
 
 
 
 
355
  $month_notice = $noticeController->getNoticeByID(self::MSG_UPGRADE_MONTH);
356
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
357
  //consider the monthly plus 1/6 of the available one-time credits.
358
+ if( $this->monthlyUpgradeNeeded($quotaData)) {
359
 
360
  if ($month_notice === false)
361
  {
384
  }
385
 
386
 
 
 
 
 
 
 
 
 
 
 
 
 
 
387
  protected function doRemoteNotices()
388
  {
389
  $notices = $this->get_remote_notices();
452
  }
453
  elseif ($viewMode !== "list")
454
  {
455
+ // @todo The notice is user-dependent but the notice is dismissed installation-wide.
456
+
457
  $message = __('You can see ShortPixel Image Optimiser actions and data only via the list view. Switch to the list view to use the plugin via the media library', 'shortpixel-image-optimiser');
458
  $new_notice = Notices::addNormal($message);
459
  Notices::makePersistent($new_notice, self::MSG_LISTVIEW_ACTIVE, YEAR_IN_SECONDS);
674
  if(is_wp_error( $proposal )) {
675
  $proposal = array('body' => __('Error. Could not contact ShortPixel server for proposal', 'shortpixel-image-optimiser'));
676
  }
677
+ die( $proposal['body'] );
 
 
 
 
 
 
 
 
 
 
 
 
678
 
 
 
 
 
 
 
 
679
  }
680
 
681
+ private function get_remote_notices()
682
  {
683
  $transient_name = 'shortpixel_remote_notice';
684
  $transient_duration = DAY_IN_SECONDS;
class/Controller/AjaxController.php CHANGED
@@ -50,8 +50,10 @@ class AjaxController
50
  public function checkProcessorKey()
51
  {
52
  $processKey = $this->getProcessorKey();
53
- $bulkSecret = isset($_POST['bulk-secret']) ? sanitize_text_field($_POST['bulk-secret']) : false;
54
- $isBulk = isset($_POST['isBulk']) ? filter_var(sanitize_text_field($_POST['isBulk']), FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE) : false;
 
 
55
 
56
  $is_processor = false;
57
  if ($processKey == false && $bulkSecret !== false)
@@ -110,8 +112,9 @@ class AjaxController
110
  public function ajax_getItemView()
111
  {
112
  $this->checkNonce('item_view');
113
-
114
  $type = isset($_POST['type']) ? sanitize_text_field($_POST['type']) : 'media';
 
115
  $id = isset($_POST['id']) ? intval($_POST['id']) : false;
116
  $result = '';
117
 
@@ -120,17 +123,17 @@ class AjaxController
120
  if ($type == 'media')
121
  {
122
  ob_start();
123
- $control = new ListMediaViewController();
124
- $control->doColumn('wp-shortPixel', $id);
125
- $result = ob_get_contents();
126
- ob_end_clean();
127
  }
128
  if ($type == 'custom')
129
  {
130
  ob_start();
131
- $control = new OtherMediaViewController();
132
- $item = \wpSPIO()->filesystem()->getImage($id, 'custom');
133
- $control->doActionColumn($item);
134
  $result = ob_get_contents();
135
  ob_end_clean();
136
  }
@@ -160,8 +163,11 @@ class AjaxController
160
  }
161
 
162
  // Notice that POST variables are always string, so 'true', not true.
 
163
  $isBulk = (isset($_POST['isBulk']) && $_POST['isBulk'] === 'true') ? true : false;
 
164
  $queue = (isset($_POST['queues'])) ? sanitize_text_field($_POST['queues']) : 'media,custom';
 
165
  $queues = array_filter(explode(',', $queue), 'trim');
166
 
167
  $control = new OptimizeController();
@@ -177,8 +183,11 @@ class AjaxController
177
  {
178
  $this->checkNonce('ajax_request');
179
 
 
180
  $action = isset($_POST['screen_action']) ? sanitize_text_field($_POST['screen_action']) : false;
 
181
  $typeArray = isset($_POST['type']) ? array(sanitize_text_field($_POST['type'])) : array('media', 'custom');
 
182
  $id = isset($_POST['id']) ? intval($_POST['id']) : false;
183
 
184
  $json = new \stdClass;
@@ -244,6 +253,9 @@ class AjaxController
244
  $data['logFile'] = isset($_POST['loadFile']) ? sanitize_text_field($_POST['loadFile']) : null;
245
  $json = $this->loadLogFile($json, $data);
246
  break;
 
 
 
247
 
248
  default:
249
  $json->$type->message = __('Ajaxrequest - no action found', 'shorpixel-image-optimiser');
@@ -269,8 +281,6 @@ class AjaxController
269
  $id = intval($_POST['id']);
270
  $type = isset($_POST['type']) ? sanitize_text_field($_POST['type']) : 'media';
271
 
272
- $addImage = isset($_POST['optimizeType']) ? sanitize_text_field($_POST['optimizeType']) : null;
273
-
274
  $mediaItem = $this->getMediaItem($id, $type);
275
 
276
  // if order is given, remove barrier and file away.
@@ -291,28 +301,27 @@ class AjaxController
291
  * @todo Test if it works with plugin intergration
292
  *
293
  */
294
- public function onWpLrUpdateMedia()
295
  {
296
- $meta = wp_get_attachment_metadata($imageId);
 
 
297
  if(is_array($meta)) {
298
  // get rid of legacy data, otherwise it will convert
299
  if (isset($meta['ShortPixel']))
300
  unset($meta['ShortPixel']);
301
 
302
  update_post_meta($imageId, '_wp_attachment_metadata', $meta);
303
- }
304
 
305
  // Get and remove Meta
306
- $mediaItem = \wpSPIO()->filesystem->getImage($imageId, 'media');
307
- $mediaItem->deleteMeta();
308
 
309
  // Optimize
310
  $control = new OptimizeController();
311
- $json = new \stdClass;
312
- $json->$type = new \stdClass;
313
-
314
- $json->$type = $control->addItemToQueue($mediaItem);
315
- return $json;
316
 
317
  }
318
 
@@ -481,6 +490,28 @@ class AjaxController
481
  return $json;
482
  }
483
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
484
  /** Data for the compare function */
485
  public function ajax_getComparerData() {
486
 
50
  public function checkProcessorKey()
51
  {
52
  $processKey = $this->getProcessorKey();
53
+ // phpcs:ignore -- Nonce is checked
54
+ $bulkSecret = isset($_POST['bulk-secret']) ? sanitize_text_field(wp_unslash($_POST['bulk-secret'])) : false;
55
+ // phpcs:ignore -- Nonce is checked
56
+ $isBulk = isset($_POST['isBulk']) ? filter_var(sanitize_text_field(wp_unslash($_POST['isBulk'])), FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE) : false;
57
 
58
  $is_processor = false;
59
  if ($processKey == false && $bulkSecret !== false)
112
  public function ajax_getItemView()
113
  {
114
  $this->checkNonce('item_view');
115
+ // phpcs:ignore -- Nonce is checked
116
  $type = isset($_POST['type']) ? sanitize_text_field($_POST['type']) : 'media';
117
+ // phpcs:ignore -- Nonce is checked
118
  $id = isset($_POST['id']) ? intval($_POST['id']) : false;
119
  $result = '';
120
 
123
  if ($type == 'media')
124
  {
125
  ob_start();
126
+ $control = new ListMediaViewController();
127
+ $control->doColumn('wp-shortPixel', $id);
128
+ $result = ob_get_contents();
129
+ ob_end_clean();
130
  }
131
  if ($type == 'custom')
132
  {
133
  ob_start();
134
+ $control = new OtherMediaViewController();
135
+ $item = \wpSPIO()->filesystem()->getImage($id, 'custom');
136
+ $control->doActionColumn($item);
137
  $result = ob_get_contents();
138
  ob_end_clean();
139
  }
163
  }
164
 
165
  // Notice that POST variables are always string, so 'true', not true.
166
+ // phpcs:ignore -- Nonce is checked
167
  $isBulk = (isset($_POST['isBulk']) && $_POST['isBulk'] === 'true') ? true : false;
168
+ // phpcs:ignore -- Nonce is checked
169
  $queue = (isset($_POST['queues'])) ? sanitize_text_field($_POST['queues']) : 'media,custom';
170
+
171
  $queues = array_filter(explode(',', $queue), 'trim');
172
 
173
  $control = new OptimizeController();
183
  {
184
  $this->checkNonce('ajax_request');
185
 
186
+ // phpcs:ignore -- Nonce is checked
187
  $action = isset($_POST['screen_action']) ? sanitize_text_field($_POST['screen_action']) : false;
188
+ // phpcs:ignore -- Nonce is checked
189
  $typeArray = isset($_POST['type']) ? array(sanitize_text_field($_POST['type'])) : array('media', 'custom');
190
+ // phpcs:ignore -- Nonce is checked
191
  $id = isset($_POST['id']) ? intval($_POST['id']) : false;
192
 
193
  $json = new \stdClass;
253
  $data['logFile'] = isset($_POST['loadFile']) ? sanitize_text_field($_POST['loadFile']) : null;
254
  $json = $this->loadLogFile($json, $data);
255
  break;
256
+ case "redoLegacy":
257
+ $this->redoLegacy($json, $data);
258
+ break;
259
 
260
  default:
261
  $json->$type->message = __('Ajaxrequest - no action found', 'shorpixel-image-optimiser');
281
  $id = intval($_POST['id']);
282
  $type = isset($_POST['type']) ? sanitize_text_field($_POST['type']) : 'media';
283
 
 
 
284
  $mediaItem = $this->getMediaItem($id, $type);
285
 
286
  // if order is given, remove barrier and file away.
301
  * @todo Test if it works with plugin intergration
302
  *
303
  */
304
+ public function onWpLrUpdateMedia($imageId)
305
  {
306
+ /*
307
+ Should be handled by OnDelete.
308
+ $meta = wp_get_attachment_metadata($imageId);
309
  if(is_array($meta)) {
310
  // get rid of legacy data, otherwise it will convert
311
  if (isset($meta['ShortPixel']))
312
  unset($meta['ShortPixel']);
313
 
314
  update_post_meta($imageId, '_wp_attachment_metadata', $meta);
315
+ } */
316
 
317
  // Get and remove Meta
318
+ $mediaItem = \wpSPIO()->filesystem()->getImage($imageId, 'media');
319
+ $mediaItem->onDelete();
320
 
321
  // Optimize
322
  $control = new OptimizeController();
323
+ $json = $control->addItemToQueue($mediaItem);
324
+ //return $json;
 
 
 
325
 
326
  }
327
 
490
  return $json;
491
  }
492
 
493
+ protected function redoLegacy($json, $data)
494
+ {
495
+ $id = $data['id'];
496
+ $type = $data['type'];
497
+ $mediaItem = $this->getMediaItem($id, $type);
498
+
499
+ // $this->ajax_getItemView();
500
+
501
+ $mediaItem->deleteMeta(); // also does reset prevent.
502
+ delete_post_meta($id, '_shortpixel_was_converted');
503
+
504
+ //$mediaItem = $this->getMediaItem($id, $type);
505
+
506
+ /* $json->status = true;
507
+ $json->media->id = $id;
508
+ $json->media->itemView = ''; */
509
+ $json->status = true;
510
+ $json->media->id = $id;
511
+ $json->media->type = 'media';
512
+ $this->send($json);
513
+ }
514
+
515
  /** Data for the compare function */
516
  public function ajax_getComparerData() {
517
 
class/Controller/ApiKeyController.php CHANGED
@@ -31,6 +31,11 @@ class ApiKeyController extends \ShortPixel\Controller
31
  $this->model->loadKey();
32
  }
33
 
 
 
 
 
 
34
  public function getKeyForDisplay()
35
  {
36
  if (! $this->model->is_hidden())
31
  $this->model->loadKey();
32
  }
33
 
34
+ public function getKeyModel()
35
+ {
36
+ return $this->model;
37
+ }
38
+
39
  public function getKeyForDisplay()
40
  {
41
  if (! $this->model->is_hidden())
class/Controller/BulkController.php CHANGED
@@ -52,6 +52,7 @@ class BulkController
52
  if ($customOp == 'migrate' || $customOp == 'removeLegacy')
53
  {
54
  $options['numitems'] = 200;
 
55
  }
56
  $Q->setCustomBulk($customOp, $options);
57
  }
@@ -178,7 +179,7 @@ class BulkController
178
  $webpcount = $q->getCustomDataItem('webpcount');
179
  $avifcount = $q->getCustomDataItem('avifcount');
180
  $basecount = $q->getCustomDataItem('basecount');
181
-
182
  if (property_exists($stats, 'images'))
183
  $data['total_images'] = $stats->images->images_done;
184
 
52
  if ($customOp == 'migrate' || $customOp == 'removeLegacy')
53
  {
54
  $options['numitems'] = 200;
55
+
56
  }
57
  $Q->setCustomBulk($customOp, $options);
58
  }
179
  $webpcount = $q->getCustomDataItem('webpcount');
180
  $avifcount = $q->getCustomDataItem('avifcount');
181
  $basecount = $q->getCustomDataItem('basecount');
182
+
183
  if (property_exists($stats, 'images'))
184
  $data['total_images'] = $stats->images->images_done;
185
 
class/Controller/FileSystemController.php CHANGED
@@ -17,6 +17,8 @@ use ShortPixel\Model\Image\CustomImageModel as CustomImageModel;
17
  Class FileSystemController extends \ShortPixel\Controller
18
  {
19
  protected $env;
 
 
20
 
21
  public function __construct()
22
  {
@@ -39,6 +41,11 @@ Class FileSystemController extends \ShortPixel\Controller
39
  */
40
  public function getMediaImage($id)
41
  {
 
 
 
 
 
42
  $filepath = get_attached_file($id);
43
  $filepath = apply_filters('shortpixel_get_attached_file', $filepath, $id);
44
 
@@ -47,6 +54,11 @@ Class FileSystemController extends \ShortPixel\Controller
47
  return false;
48
 
49
  $imageObj = new MediaLibraryModel($id, $filepath);
 
 
 
 
 
50
  return $imageObj;
51
  }
52
 
@@ -55,7 +67,18 @@ Class FileSystemController extends \ShortPixel\Controller
55
  */
56
  public function getCustomImage($id)
57
  {
 
 
 
 
 
58
  $imageObj = new CustomImageModel($id);
 
 
 
 
 
 
59
  return $imageObj;
60
  }
61
 
17
  Class FileSystemController extends \ShortPixel\Controller
18
  {
19
  protected $env;
20
+ static $mediaItems = array();
21
+ static $customItems = array();
22
 
23
  public function __construct()
24
  {
41
  */
42
  public function getMediaImage($id)
43
  {
44
+ if (isset(self::$mediaItems[$id]))
45
+ {
46
+ return self::$mediaItems[$id];
47
+ }
48
+
49
  $filepath = get_attached_file($id);
50
  $filepath = apply_filters('shortpixel_get_attached_file', $filepath, $id);
51
 
54
  return false;
55
 
56
  $imageObj = new MediaLibraryModel($id, $filepath);
57
+
58
+ if (is_object($imageObj))
59
+ {
60
+ self::$mediaItems[$id] = $imageObj;
61
+ }
62
  return $imageObj;
63
  }
64
 
67
  */
68
  public function getCustomImage($id)
69
  {
70
+ if (isset(self::$customItems[$id]))
71
+ {
72
+ return self::$customItems[$id];
73
+ }
74
+
75
  $imageObj = new CustomImageModel($id);
76
+
77
+ if (is_object($imageObj))
78
+ {
79
+ self::$customItems[$id] = $imageObj;
80
+ }
81
+
82
  return $imageObj;
83
  }
84
 
class/Controller/FrontController.php CHANGED
@@ -28,14 +28,14 @@ class FrontController extends \ShortPixel\Controller
28
  {
29
  $webp_option = \wpSPIO()->settings()->deliverWebp;
30
 
31
- if ( $webp_option ) {
32
  if(\ShortPixelTools::shortPixelIsPluginActive('shortpixel-adaptive-images/short-pixel-ai.php')) {
33
  Notices::addWarning(__('Please deactivate the ShortPixel Image Optimizer\'s
34
  <a href="options-general.php?page=wp-shortpixel-settings&part=adv-settings">Deliver the next generation versions of the images in the front-end</a>
35
  option when the ShortPixel Adaptive Images plugin is active.','shortpixel-image-optimiser'), true);
36
  }
37
  elseif( $webp_option == self::WEBP_GLOBAL ){
38
- add_action( 'wp_head', array($this, 'addPictureJs') ); // adds polyfill JS to the header
39
  add_action( 'init', array($this, 'startOutputBuffer'), 1 ); // start output buffer to capture content
40
  } elseif ($webp_option == self::WEBP_WP){
41
  add_filter( 'the_content', array($this, 'convertImgToPictureAddWebp'), 10000 ); // priority big, so it will be executed last
@@ -54,30 +54,15 @@ class FrontController extends \ShortPixel\Controller
54
 
55
  if(function_exists('is_amp_endpoint') && is_amp_endpoint()) {
56
  //for AMP pages the <picture> tag is not allowed
 
57
  return $content . (isset($_GET['SHORTPIXEL_DEBUG']) ? '<!-- SPDBG is AMP -->' : '');
58
  }
59
  require_once(\ShortPixelTools::getPluginPath() . 'class/front/img-to-picture-webp.php');
60
 
61
  $webpObj = new ShortPixelImgToPictureWebp();
62
  return $webpObj->convert($content);
63
- // return \::convert($content);// . "<!-- PICTURE TAGS BY SHORTPIXEL -->";
64
  }
65
 
66
- public function addPictureJs() {
67
- // Don't do anything with the RSS feed.
68
- if ( is_feed() || is_admin() ) { return; }
69
-
70
- echo '<script>'
71
- . 'var spPicTest = document.createElement( "picture" );'
72
- . 'if(!window.HTMLPictureElement && document.addEventListener) {'
73
- . 'window.addEventListener("DOMContentLoaded", function() {'
74
- . 'var scriptTag = document.createElement("script");'
75
- . 'scriptTag.src = "' . plugins_url('/res/js/picturefill.min.js', SHORTPIXEL_PLUGIN_FILE) . '";'
76
- . 'document.body.appendChild(scriptTag);'
77
- . '});'
78
- . '}'
79
- . '</script>';
80
- }
81
 
82
 
83
  public function startOutputBuffer() {
28
  {
29
  $webp_option = \wpSPIO()->settings()->deliverWebp;
30
 
31
+ if ( $webp_option ) { // @tood Replace this function with the one in ENV.
32
  if(\ShortPixelTools::shortPixelIsPluginActive('shortpixel-adaptive-images/short-pixel-ai.php')) {
33
  Notices::addWarning(__('Please deactivate the ShortPixel Image Optimizer\'s
34
  <a href="options-general.php?page=wp-shortpixel-settings&part=adv-settings">Deliver the next generation versions of the images in the front-end</a>
35
  option when the ShortPixel Adaptive Images plugin is active.','shortpixel-image-optimiser'), true);
36
  }
37
  elseif( $webp_option == self::WEBP_GLOBAL ){
38
+ //add_action( 'wp_head', array($this, 'addPictureJs') ); // adds polyfill JS to the header || Removed. Browsers without picture support?
39
  add_action( 'init', array($this, 'startOutputBuffer'), 1 ); // start output buffer to capture content
40
  } elseif ($webp_option == self::WEBP_WP){
41
  add_filter( 'the_content', array($this, 'convertImgToPictureAddWebp'), 10000 ); // priority big, so it will be executed last
54
 
55
  if(function_exists('is_amp_endpoint') && is_amp_endpoint()) {
56
  //for AMP pages the <picture> tag is not allowed
57
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is not a form
58
  return $content . (isset($_GET['SHORTPIXEL_DEBUG']) ? '<!-- SPDBG is AMP -->' : '');
59
  }
60
  require_once(\ShortPixelTools::getPluginPath() . 'class/front/img-to-picture-webp.php');
61
 
62
  $webpObj = new ShortPixelImgToPictureWebp();
63
  return $webpObj->convert($content);
 
64
  }
65
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
 
67
 
68
  public function startOutputBuffer() {
class/Controller/OptimizeController.php CHANGED
@@ -289,7 +289,6 @@ class OptimizeController
289
  $data->media->stats = $mediaQ->getStats();
290
  $data->custom->stats = $customQ->getStats();
291
 
292
-
293
  $data->total = $this->calculateStatsTotals($data);
294
  $data = $this->numberFormatStats($data);
295
 
@@ -654,9 +653,6 @@ class OptimizeController
654
  $newItem = new \stdClass;
655
  $newItem->urls = $imageItem->getOptimizeUrls();
656
 
657
- //$webps = ($imageItem->isProcessableFileType('webp')) ? $imageItem->getOptimizeFileType('webp') : array();
658
- //$avifs = ($imageItem->isProcessableFileType('avigetQueueNamef')) ? $imageItem->getOptimizeFileType('avif') : array();
659
-
660
  // Add to URLs also the possiblity of images with only webp / avif needs. Otherwise URLs would end up emtpy.
661
  //$newItem->urls = array_merge($newItem->urls, $webps, $avifs);
662
 
289
  $data->media->stats = $mediaQ->getStats();
290
  $data->custom->stats = $customQ->getStats();
291
 
 
292
  $data->total = $this->calculateStatsTotals($data);
293
  $data = $this->numberFormatStats($data);
294
 
653
  $newItem = new \stdClass;
654
  $newItem->urls = $imageItem->getOptimizeUrls();
655
 
 
 
 
656
  // Add to URLs also the possiblity of images with only webp / avif needs. Otherwise URLs would end up emtpy.
657
  //$newItem->urls = array_merge($newItem->urls, $webps, $avifs);
658
 
class/Controller/OtherMediaController.php CHANGED
@@ -314,28 +314,48 @@ class OtherMediaController extends \ShortPixel\Controller
314
  {
315
  $fs = \wpSPIO()->filesystem();
316
  $uploadDir = $fs->getWPUploadBase();
 
317
 
318
- // if it's the uploads base dir, the media library would be included, so don't allow.
 
 
319
  if ($directory->getPath() == $uploadDir->getPath() )
 
 
 
 
 
320
  return true;
321
- elseif (! $directory->isSubFolderOf($uploadDir))// The easy check. No subdir, no problem.
322
- return false;
323
- elseif (is_numeric($directory->getName() )) // upload subdirs come in variation of year or month, both numeric.
324
- return true;
 
 
 
 
 
 
 
 
 
 
 
 
325
  }
326
 
327
 
328
  public function ajaxBrowseContent()
329
  {
330
  if ( ! $this->userIsAllowed ) {
331
- wp_die(__('You do not have sufficient permissions to access this page.','shortpixel-image-optimiser'));
332
  }
333
  $fs = \wpSPIO()->filesystem();
334
  $rootDirObj = $fs->getWPFileBase();
335
  $path = $rootDirObj->getPath();
336
 
337
-
338
- $postDir = isset($_POST['dir']) ? trim(sanitize_text_field($_POST['dir'])) : null;
339
  if (! is_null($postDir))
340
  {
341
  $postDir = rawurldecode($postDir);
@@ -348,14 +368,13 @@ class OtherMediaController extends \ShortPixel\Controller
348
 
349
  $path .= '/' . $child;
350
  }
351
-
352
  }
353
 
354
  $dirObj = $fs->getDirectory($path);
355
 
356
  if ($dirObj->getPath() !== $rootDirObj->getPath() && ! $dirObj->isSubFolderOf($rootDirObj))
357
  {
358
- exit( __('This directory seems not part of WordPress', 'shortpixel-image-optimiser'));
359
  }
360
 
361
  if( $dirObj->exists() ) {
@@ -368,7 +387,8 @@ class OtherMediaController extends \ShortPixel\Controller
368
  foreach($subdirs as $index => $dir) // weed out the media library subdirectories.
369
  {
370
  $dirname = $dir->getName();
371
- if($dirname == 'ShortpixelBackups' || $this->checkifMediaLibrary($dir))
 
372
  {
373
  unset($subdirs[$index]);
374
  }
@@ -386,7 +406,7 @@ class OtherMediaController extends \ShortPixel\Controller
386
  $htmlName = htmlentities($dirname);
387
  //$ext = preg_replace('/^.*\./', '', $file);
388
 
389
- if( $dir->exists() ) {
390
  //KEEP the spaces in front of the rel values - it's a trick to make WP Hide not replace the wp-content path
391
  echo "<li class='directory collapsed'><a rel=' " .esc_attr($htmlRel) . "'>" . esc_html($htmlName) . "</a></li>";
392
  }
@@ -398,7 +418,7 @@ class OtherMediaController extends \ShortPixel\Controller
398
  elseif ($_POST['dir'] == '/')
399
  {
400
  echo "<ul class='jqueryFileTree'>";
401
- _e('No Directories found that can be added to Custom Folders', 'shortpixel-image-optimiser');
402
  echo "</ul>";
403
  }
404
  }
314
  {
315
  $fs = \wpSPIO()->filesystem();
316
  $uploadDir = $fs->getWPUploadBase();
317
+ $wpUploadDir = wp_upload_dir(null, false);
318
 
319
+ $is_year_based = (isset($wpUploadDir['subdir']) && strlen(trim($wpUploadDir['subdir'])) > 0) ? true : false;
320
+
321
+ // if it's the uploads base dir, check if the library is year-based, then allow. If all files are in uploads root, don't allow.
322
  if ($directory->getPath() == $uploadDir->getPath() )
323
+ {
324
+ if ($is_year_based)
325
+ {
326
+ return false;
327
+ }
328
  return true;
329
+ }
330
+ elseif (! $directory->isSubFolderOf($uploadDir))// The easy check. No subdir of uploads, no problem.
331
+ {
332
+ return false;
333
+ }
334
+ elseif ($directory->isSubFolderOf($uploadDir)) // upload subdirs come in variation of year or month, both numeric. Exclude the WP-based years
335
+ {
336
+ $name = $directory->getName();
337
+ if (is_numeric($name) && strlen($name) == 4) // exclude year based stuff.
338
+ {
339
+ return true;
340
+ }
341
+ else {
342
+ return false;
343
+ }
344
+ }
345
  }
346
 
347
 
348
  public function ajaxBrowseContent()
349
  {
350
  if ( ! $this->userIsAllowed ) {
351
+ wp_die(esc_html(__('You do not have sufficient permissions to access this page.','shortpixel-image-optimiser')));
352
  }
353
  $fs = \wpSPIO()->filesystem();
354
  $rootDirObj = $fs->getWPFileBase();
355
  $path = $rootDirObj->getPath();
356
 
357
+ // @todo Add Nonce here
358
+ $postDir = isset($_POST['dir']) ? trim(sanitize_text_field(wp_unslash($_POST['dir']))) : null;
359
  if (! is_null($postDir))
360
  {
361
  $postDir = rawurldecode($postDir);
368
 
369
  $path .= '/' . $child;
370
  }
 
371
  }
372
 
373
  $dirObj = $fs->getDirectory($path);
374
 
375
  if ($dirObj->getPath() !== $rootDirObj->getPath() && ! $dirObj->isSubFolderOf($rootDirObj))
376
  {
377
+ exit(esc_html(__('This directory seems not part of WordPress', 'shortpixel-image-optimiser')));
378
  }
379
 
380
  if( $dirObj->exists() ) {
387
  foreach($subdirs as $index => $dir) // weed out the media library subdirectories.
388
  {
389
  $dirname = $dir->getName();
390
+ // @todo This should probably be checked via getBackupDirectory or so, not hardcoded ShortipxelBackups
391
+ if($dirname == 'ShortpixelBackups' || $this->checkifMediaLibrary($dir) )
392
  {
393
  unset($subdirs[$index]);
394
  }
406
  $htmlName = htmlentities($dirname);
407
  //$ext = preg_replace('/^.*\./', '', $file);
408
 
409
+ if( $dir->exists() ) {
410
  //KEEP the spaces in front of the rel values - it's a trick to make WP Hide not replace the wp-content path
411
  echo "<li class='directory collapsed'><a rel=' " .esc_attr($htmlRel) . "'>" . esc_html($htmlName) . "</a></li>";
412
  }
418
  elseif ($_POST['dir'] == '/')
419
  {
420
  echo "<ul class='jqueryFileTree'>";
421
+ esc_html_e('No Directories found that can be added to Custom Folders', 'shortpixel-image-optimiser');
422
  echo "</ul>";
423
  }
424
  }
class/Controller/Queue/Queue.php CHANGED
@@ -58,6 +58,7 @@ abstract class Queue
58
 
59
  public function resetQueue()
60
  {
 
61
  $this->q->resetQueue();
62
  }
63
 
@@ -179,8 +180,6 @@ abstract class Queue
179
  $queue = array();
180
  $imageCount = $webpCount = $avifCount = $baseCount = 0;
181
 
182
- //$customData = $this->getStatus('custom_data');
183
-
184
  $operation = $this->getCustomDataItem('customOperation'); // false or value (or null)
185
 
186
  if (is_null($operation))
@@ -245,6 +244,7 @@ abstract class Queue
245
  }
246
  else
247
  {
 
248
  $response = array(
249
  'is_error' => true,
250
  'item_type' => ResponseController::ISSUE_QUEUE_FAILED,
58
 
59
  public function resetQueue()
60
  {
61
+ Log::addTemp('Resetting Queue: ' . $this->getQueueName());
62
  $this->q->resetQueue();
63
  }
64
 
180
  $queue = array();
181
  $imageCount = $webpCount = $avifCount = $baseCount = 0;
182
 
 
 
183
  $operation = $this->getCustomDataItem('customOperation'); // false or value (or null)
184
 
185
  if (is_null($operation))
244
  }
245
  else
246
  {
247
+ Log::addTemp('MediaItem not is processable');
248
  $response = array(
249
  'is_error' => true,
250
  'item_type' => ResponseController::ISSUE_QUEUE_FAILED,
class/Controller/QuotaController.php CHANGED
@@ -159,6 +159,7 @@ class QuotaController
159
  {
160
  $keyControl = ApiKeyController::getInstance();
161
  $apiKey = $keyControl->forceGetApiKey();
 
162
  }
163
 
164
 
@@ -175,12 +176,11 @@ class QuotaController
175
  );
176
  $argsStr = "?key=".$apiKey;
177
 
178
- //if($appendUserAgent) { // See no reason why not(?)
179
- $args['body']['useragent'] = "Agent" . urlencode($_SERVER['HTTP_USER_AGENT']);
180
- $argsStr .= "&useragent=Agent".$args['body']['useragent'];
181
- //}
182
 
183
- // Only used for keyValidation!
184
  if($validate) {
185
 
186
  $statsController = StatsController::getInstance();
159
  {
160
  $keyControl = ApiKeyController::getInstance();
161
  $apiKey = $keyControl->forceGetApiKey();
162
+ Log::addTemp('ApiKey for remoteQuota ' . $apiKey);
163
  }
164
 
165
 
176
  );
177
  $argsStr = "?key=".$apiKey;
178
 
179
+ $serverAgent = isset($_SERVER['HTTP_USER_AGENT']) ? urlencode(sanitize_text_field(wp_unslash($_SERVER['HTTP_USER_AGENT']))) : '';
180
+ $args['body']['useragent'] = "Agent" . $serverAgent;
181
+ $argsStr .= "&useragent=Agent".$args['body']['useragent'];
 
182
 
183
+ // Only used for keyValidation
184
  if($validate) {
185
 
186
  $statsController = StatsController::getInstance();
class/Controller/SettingsController.php CHANGED
@@ -24,7 +24,6 @@ class SettingsController extends \ShortPixel\ViewController
24
  protected $hide_api_key;
25
  protected $has_nextgen;
26
  protected $do_redirect = false;
27
- protected $postkey_needs_validation = false;
28
 
29
  protected $quotaData = null;
30
 
@@ -42,9 +41,12 @@ class SettingsController extends \ShortPixel\ViewController
42
  public function __construct()
43
  {
44
  $this->model = \wpSPIO()->settings();
45
- $this->keyModel = new ApiKeyModel();
46
 
47
- $this->keyModel->loadKey();
 
 
 
 
48
  $this->is_verifiedkey = $this->keyModel->is_verified();
49
  $this->is_constant_key = $this->keyModel->is_constant();
50
  $this->hide_api_key = $this->keyModel->is_hidden();
@@ -194,14 +196,8 @@ class SettingsController extends \ShortPixel\ViewController
194
 
195
  public function action_debug_redirectBulk()
196
  {
197
- $opt = new OptimizeController();
198
- $opt->setBulk(true);
199
-
200
- $bulkMedia = $opt->getQueue('media');
201
- $bulkCustom = $opt->getQueue('custom');
202
 
203
- $bulkMedia->resetQueue();
204
- $bulkCustom->resetQueue();
205
 
206
  $action = isset($_REQUEST['bulk']) ? sanitize_text_field($_REQUEST['bulk']) : null;
207
 
@@ -314,7 +310,6 @@ class SettingsController extends \ShortPixel\ViewController
314
 
315
  public function processSave()
316
  {
317
-
318
  // Split this in the several screens. I.e. settings, advanced, Key Request IF etc.
319
  if (isset($this->postData['includeNextGen']) && $this->postData['includeNextGen'] == 1)
320
  {
@@ -353,7 +348,8 @@ class SettingsController extends \ShortPixel\ViewController
353
  }
354
 
355
 
356
- // Every save, force load the quota. One reason, because of the HTTP Auth settings refresh.
 
357
  $this->loadQuotaData(true);
358
 
359
  // end
@@ -688,14 +684,7 @@ class SettingsController extends \ShortPixel\ViewController
688
  // must be an array
689
  $post['excludeSizes'] = (isset($post['excludeSizes']) && is_array($post['excludeSizes']) ? $post['excludeSizes']: array());
690
 
691
- // key check, if validate is set to valid, check the key
692
- if (isset($post['validate']))
693
- {
694
- if ($post['validate'] == 'validate')
695
- $this->postkey_needs_validation = true;
696
 
697
- unset($post['validate']);
698
- }
699
 
700
  // when adding a new custom folder
701
  if (isset($post['addCustomFolder']) && strlen($post['addCustomFolder']) > 0)
@@ -712,7 +701,6 @@ class SettingsController extends \ShortPixel\ViewController
712
  unset($post['addCustomFolder']);
713
 
714
  if(isset($post['removeFolder']) && intval($post['removeFolder']) > 0) {
715
- //$metaDao = $this->shortPixel->getSpMetaDao();
716
  $folder_id = intval($post['removeFolder']);
717
  $otherMedia = OtherMediaController::getInstance();
718
  $dirObj = $otherMedia->getFolderByID($folder_id);
24
  protected $hide_api_key;
25
  protected $has_nextgen;
26
  protected $do_redirect = false;
 
27
 
28
  protected $quotaData = null;
29
 
41
  public function __construct()
42
  {
43
  $this->model = \wpSPIO()->settings();
 
44
 
45
+ //@todo Streamline this mess. Should run through controller mostly. Risk of desync otherwise.
46
+ $keyControl = ApiKeyController::getInstance();
47
+ $this->keyModel = $keyControl->getKeyModel(); //new ApiKeyModel();
48
+
49
+ // $this->keyModel->loadKey();
50
  $this->is_verifiedkey = $this->keyModel->is_verified();
51
  $this->is_constant_key = $this->keyModel->is_constant();
52
  $this->hide_api_key = $this->keyModel->is_hidden();
196
 
197
  public function action_debug_redirectBulk()
198
  {
 
 
 
 
 
199
 
200
+ OptimizeController::resetQueues();
 
201
 
202
  $action = isset($_REQUEST['bulk']) ? sanitize_text_field($_REQUEST['bulk']) : null;
203
 
310
 
311
  public function processSave()
312
  {
 
313
  // Split this in the several screens. I.e. settings, advanced, Key Request IF etc.
314
  if (isset($this->postData['includeNextGen']) && $this->postData['includeNextGen'] == 1)
315
  {
348
  }
349
 
350
 
351
+ // Every save, force load the quota. One reason, because of the HTTP Auth settings refresh.
352
+ Log::addTemp('calling load Quota');
353
  $this->loadQuotaData(true);
354
 
355
  // end
684
  // must be an array
685
  $post['excludeSizes'] = (isset($post['excludeSizes']) && is_array($post['excludeSizes']) ? $post['excludeSizes']: array());
686
 
 
 
 
 
 
687
 
 
 
688
 
689
  // when adding a new custom folder
690
  if (isset($post['addCustomFolder']) && strlen($post['addCustomFolder']) > 0)
701
  unset($post['addCustomFolder']);
702
 
703
  if(isset($post['removeFolder']) && intval($post['removeFolder']) > 0) {
 
704
  $folder_id = intval($post['removeFolder']);
705
  $otherMedia = OtherMediaController::getInstance();
706
  $dirObj = $otherMedia->getFolderByID($folder_id);
class/Controller/View/BulkRestoreAll.php DELETED
@@ -1,90 +0,0 @@
1
- <?php
2
- namespace ShortPixel\Controller\View;
3
- use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
-
5
- use \ShortPixel\Controller\OtherMediaController as OtherMediaController;
6
-
7
- class BulkRestoreAll extends \ShortPixel\ViewController
8
- {
9
- protected static $slug = 'bulk-restore-all';
10
- protected $template = 'view-restore-all';
11
- protected $form_action = 'sp-bulk';
12
-
13
- protected $selected_folders = array();
14
-
15
- public function __construct()
16
- {
17
- parent::__construct();
18
-
19
- }
20
-
21
- public function load()
22
- {
23
- $this->loadView();
24
- }
25
-
26
- public function randomCheck()
27
- {
28
-
29
- $output = '';
30
- for ($i=1; $i<= 10; $i++)
31
- {
32
- $output .= "<span><input type='radio' name='random_check[]' value='$i' onchange='ShortPixel.checkRandomAnswer(event)' /> $i </span>";
33
- }
34
-
35
- return $output;
36
- }
37
-
38
- public function randomAnswer()
39
- {
40
- $correct = rand(1,10);
41
- $output = "<input type='hidden' name='random_answer' value='$correct' data-target='#bulkRestore' /> <span class='answer'>$correct</span> ";
42
-
43
- return $output;
44
- }
45
-
46
- public function getCustomFolders()
47
- {
48
-
49
- $otherMedia = OtherMediaController::getInstance();
50
-
51
- return $otherMedia->getAllFolders();
52
-
53
- }
54
-
55
- protected function processPostData($post)
56
- {
57
- if (isset($post['selected_folders']))
58
- {
59
- $folders = array_filter($post['selected_folders'], 'intval');
60
- if (count($folders) > 0)
61
- {
62
- $this->selected_folders = $folders;
63
- }
64
- unset($post['selected_folders']);
65
- }
66
-
67
- parent::processPostData($post);
68
-
69
- }
70
-
71
- public function setupBulk()
72
- {
73
- // Not doing this, since it's deliverd from bulk_view_controller. Yes, this is hacky. Prob. controller should merge.
74
- // $this->checkPost(); // check if any POST vars are there ( which should be if custom restore is on )
75
- $selected_folders = isset($_POST['selected_folders']) ? $_POST['selected_folders'] : array();
76
-
77
- // handle the custom folders if there are any.
78
- if (count($selected_folders) > 0)
79
- {
80
- $spMetaDao = \wpSPIO()->getShortPixel()->getSpMetaDao();
81
-
82
- foreach($selected_folders as $folder_id)
83
- {
84
- $spMetaDao->setBulkRestore($folder_id);
85
- }
86
- }
87
- }
88
-
89
-
90
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
class/Controller/View/EditMediaViewController.php CHANGED
@@ -68,7 +68,6 @@ class EditMediaViewController extends \ShortPixel\ViewController
68
  return false;
69
  }
70
 
71
-
72
  $this->view->status_message = null;
73
 
74
  $this->view->text = UiHelper::getStatusText($this->imageModel);
@@ -147,10 +146,7 @@ class EditMediaViewController extends \ShortPixel\ViewController
147
  $meta = \wp_get_attachment_metadata($this->post_id);
148
 
149
  $fs = \wpSPIO()->filesystem();
150
- //$imageObj = $fs->getMediaImage($this->post_id);
151
- /*$imageObj = new ImageModel();
152
- $imageObj->setByPostID($this->post_id); */
153
- // $imageFile = //$imageObj->getFile();
154
  $imageObj = $this->imageModel;
155
 
156
  if ($imageObj->isProcessable())
@@ -190,7 +186,7 @@ class EditMediaViewController extends \ShortPixel\ViewController
190
 
191
  if ($imageObj->is_virtual())
192
  {
193
- $debugInfo[] = array(__('Is Virtual'), $imageObj->getFullPath() );
194
  }
195
 
196
  $debugInfo[] = array(__('Size and Mime (ImageObj)'), $imageObj->get('width') . 'x' . $imageObj->get('height'). ' (' . $imageObj->get('mime') . ')');
68
  return false;
69
  }
70
 
 
71
  $this->view->status_message = null;
72
 
73
  $this->view->text = UiHelper::getStatusText($this->imageModel);
146
  $meta = \wp_get_attachment_metadata($this->post_id);
147
 
148
  $fs = \wpSPIO()->filesystem();
149
+
 
 
 
150
  $imageObj = $this->imageModel;
151
 
152
  if ($imageObj->isProcessable())
186
 
187
  if ($imageObj->is_virtual())
188
  {
189
+ $debugInfo[] = array(__('Is Virtual'), $imageObj->getFullPath() );
190
  }
191
 
192
  $debugInfo[] = array(__('Size and Mime (ImageObj)'), $imageObj->get('width') . 'x' . $imageObj->get('height'). ' (' . $imageObj->get('mime') . ')');
class/Controller/View/ListMediaViewController.php CHANGED
@@ -197,9 +197,11 @@ class ListMediaViewController extends \ShortPixel\ViewController
197
  public function filterBy($vars)
198
  {
199
  // Must return postID's as ID
 
200
  if ( 'upload.php' == $GLOBALS['pagenow'] && isset( $_GET['shortpixel_status'] ) ) {
201
 
202
- $status = sanitize_text_field($_GET['shortpixel_status']);
 
203
 
204
  if ($status == 'all')
205
  {
@@ -230,10 +232,7 @@ class ListMediaViewController extends \ShortPixel\ViewController
230
  public function parseQuery($request, $wpquery)
231
  {
232
  global $wpdb;
233
- // echo "<PRE style='margin-left: 400px; '>"; var_dump($wpquery->query_vars); var_dump($request); echo "</PRE>";
234
 
235
- // @todo The order is not working. Can be made to work but already is not scaling in performance ( very heavy )
236
- // @todo2 Unoptimized can only work in case of restore but not new files, because those are not in the database yet!
237
  if (isset($wpquery->query_vars['shortpixel-filter']) || isset($wpquery->query_vars['shortpixel-order']) )
238
  {
239
  $filter = isset($wpquery->query_vars['shortpixel-filter']) ? $wpquery->query_vars['shortpixel-filter'] : false ;
@@ -254,14 +253,14 @@ class ListMediaViewController extends \ShortPixel\ViewController
254
 
255
  if ($filter && $filter == 'optimized')
256
  {
257
- $sql = ' SELECT attach_id AS ID FROM ' . $tableName;
258
  $sql .= ' INNER JOIN ' . $wpdb->posts . ' ON ' . $wpdb->posts . '.ID = ' . $tableName . '.attach_id ';
259
 
260
  $sql .= 'WHERE image_type = %d AND status = %d';
261
  $sql = $wpdb->prepare($sql, MediaLibraryModel::IMAGE_TYPE_MAIN, $fileStatus);
262
  $sql .= ' AND ' . $post_where; // glue back the orders, and the all.
263
  }
264
- if ($filter == 'unoptimized')
265
  {
266
  $where = " AND " . $wpdb->posts . '.ID not in ( SELECT attach_id FROM ' . $tableName . " WHERE parent = %d and status = %d) ";
267
  $where = $wpdb->prepare($where, MediaLibraryModel::IMAGE_TYPE_MAIN, ImageModel::FILE_STATUS_SUCCESS);
@@ -300,10 +299,10 @@ class ListMediaViewController extends \ShortPixel\ViewController
300
  // 'error' => __('Errors', 'shortpixel-image-optimiser'),
301
  );
302
 
303
- echo "<select name='shortpixel_status' id='shortpixel_status'>\n";
304
  foreach($options as $optname => $optval)
305
  {
306
- $selected = ($status == $optname) ? 'selected' : '';
307
  echo "<option value='". esc_attr($optname) . "' $selected >" . esc_html($optval) . "</option>\n";
308
  }
309
  echo "</select>";
197
  public function filterBy($vars)
198
  {
199
  // Must return postID's as ID
200
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is not a form
201
  if ( 'upload.php' == $GLOBALS['pagenow'] && isset( $_GET['shortpixel_status'] ) ) {
202
 
203
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is not a form
204
+ $status = sanitize_text_field(wp_unslash($_GET['shortpixel_status']));
205
 
206
  if ($status == 'all')
207
  {
232
  public function parseQuery($request, $wpquery)
233
  {
234
  global $wpdb;
 
235
 
 
 
236
  if (isset($wpquery->query_vars['shortpixel-filter']) || isset($wpquery->query_vars['shortpixel-order']) )
237
  {
238
  $filter = isset($wpquery->query_vars['shortpixel-filter']) ? $wpquery->query_vars['shortpixel-filter'] : false ;
253
 
254
  if ($filter && $filter == 'optimized')
255
  {
256
+ $sql = ' SELECT * FROM ' . $tableName;
257
  $sql .= ' INNER JOIN ' . $wpdb->posts . ' ON ' . $wpdb->posts . '.ID = ' . $tableName . '.attach_id ';
258
 
259
  $sql .= 'WHERE image_type = %d AND status = %d';
260
  $sql = $wpdb->prepare($sql, MediaLibraryModel::IMAGE_TYPE_MAIN, $fileStatus);
261
  $sql .= ' AND ' . $post_where; // glue back the orders, and the all.
262
  }
263
+ if ($filter && $filter == 'unoptimized')
264
  {
265
  $where = " AND " . $wpdb->posts . '.ID not in ( SELECT attach_id FROM ' . $tableName . " WHERE parent = %d and status = %d) ";
266
  $where = $wpdb->prepare($where, MediaLibraryModel::IMAGE_TYPE_MAIN, ImageModel::FILE_STATUS_SUCCESS);
299
  // 'error' => __('Errors', 'shortpixel-image-optimiser'),
300
  );
301
 
302
+ echo "<select name='shortpixel_status' id='shortpixel_status'>\n";
303
  foreach($options as $optname => $optval)
304
  {
305
+ $selected = ($status == $optname) ? esc_attr('selected') : '';
306
  echo "<option value='". esc_attr($optname) . "' $selected >" . esc_html($optval) . "</option>\n";
307
  }
308
  echo "</select>";
class/Controller/View/OtherMediaViewController.php CHANGED
@@ -36,11 +36,17 @@ class OtherMediaViewController extends \ShortPixel\ViewController
36
  parent::__construct();
37
  $this->setActions(); // possible actions for ROWS only..
38
 
 
 
39
  $this->currentPage = isset($_GET['paged']) ? intval($_GET['paged']) : 1;
40
- $this->orderby = ( ! empty( $_GET['orderby'] ) ) ? $this->filterAllowedOrderBy(sanitize_text_field($_GET['orderby'])) : 'id';
41
- $this->order = ( ! empty($_GET['order'] ) ) ? sanitize_text_field($_GET['order']) : 'desc'; // If no order, default to asc
42
- $this->search = (isset($_GET["s"]) && strlen($_GET["s"])) ? sanitize_text_field($_GET['s']) : false;
43
- $this->show_hidden = isset($_GET['show_hidden']) ? sanitize_text_field($_GET['show_hidden']) : false;
 
 
 
 
44
 
45
  }
46
 
@@ -61,7 +67,7 @@ class OtherMediaViewController extends \ShortPixel\ViewController
61
 
62
  public function action_refreshfolders()
63
  {
64
- if (wp_verify_nonce( $_REQUEST['_wpnonce'], 'refresh_folders'))
65
  {
66
  $otherMediaController = OtherMediaController::getInstance();
67
  $otherMediaController->refreshFolders(true);
@@ -206,8 +212,12 @@ class OtherMediaViewController extends \ShortPixel\ViewController
206
 
207
  protected function getFilter() {
208
  $filter = array();
209
- if(isset($_GET["s"]) && strlen($_GET["s"])) {
210
- $filter['path'] = (object)array("operator" => "like", "value" =>"'%" . esc_sql($_GET["s"]) . "%'");
 
 
 
 
211
  }
212
  return $filter;
213
  }
@@ -335,10 +345,10 @@ class OtherMediaViewController extends \ShortPixel\ViewController
335
  $total_pages_before = '<span class="paging-input">';
336
  $total_pages_after = '</span></span>';
337
 
338
- $current_url = remove_query_arg( 'paged', $this->getPageURL()); // has url
339
 
340
- $output = '<form method="GET" action="'. $current_url . '">'; //'<span class="pagination-links">';
341
- $output .= '<span class="displaying-num">'. sprintf(__('%d Images', 'shortpixel-image-optimiser'), $this->total_items) . '</span>';
342
 
343
  if ( $disable_first ) {
344
  $page_links[] = '<span class="tablenav-pages-navspan button disabled" aria-hidden="true">&laquo;</span>';
@@ -346,7 +356,7 @@ class OtherMediaViewController extends \ShortPixel\ViewController
346
  $page_links[] = sprintf(
347
  "<a class='first-page button' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
348
  esc_url( $current_url ),
349
- __( 'First page' ),
350
  '&laquo;'
351
  );
352
  }
@@ -357,14 +367,14 @@ class OtherMediaViewController extends \ShortPixel\ViewController
357
  $page_links[] = sprintf(
358
  "<a class='prev-page button' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
359
  esc_url( add_query_arg( 'paged', max( 1, $current - 1 ), $current_url ) ),
360
- __( 'Previous page' ),
361
  '&lsaquo;'
362
  );
363
  }
364
 
365
  $html_current_page = sprintf(
366
  "%s<input class='current-page' id='current-page-selector' type='text' name='paged' value='%s' size='%d' aria-describedby='table-paging' /><span class='tablenav-paging-text'>",
367
- '<label for="current-page-selector" class="screen-reader-text">' . __( 'Current Page' ) . '</label>',
368
  $current,
369
  strlen( $pages )
370
  );
@@ -462,8 +472,9 @@ class OtherMediaViewController extends \ShortPixel\ViewController
462
  $classes = ($action['display'] == 'button') ? " button-smaller button-primary $actionName " : "$actionName";
463
  $link = ($action['type'] == 'js') ? 'javascript:' . $action['function'] : $action['function'];
464
 
 
465
  ?>
466
- <a href="<?php echo esc_url($link) ?>" class="<?php echo esc_attr($classes) ?>"><?php echo esc_html($action['text']) ?></a>
467
 
468
  <?php
469
  endforeach;
@@ -472,10 +483,11 @@ class OtherMediaViewController extends \ShortPixel\ViewController
472
  }
473
 
474
 
475
- // Used for row actions at the moment.
476
  protected function renderActions($actions, $item, $forceSingular = false)
477
  {
478
 
 
479
  foreach($actions as $index => $action)
480
  {
481
  $text = isset($action['text']) ? $action['text'] : '';
@@ -499,7 +511,6 @@ class OtherMediaViewController extends \ShortPixel\ViewController
499
  $url = add_query_arg('type', $action['type'], $url);
500
  $class = (isset($action['class'])) ? $action['class'] : '';
501
 
502
-
503
  $link = '<a href="' . esc_url($url) . '" class="action-' . esc_attr($action_arg) . ' ' . esc_attr($class) . '">' . esc_html($text) . '</a>';
504
  }
505
 
@@ -546,7 +557,7 @@ class OtherMediaViewController extends \ShortPixel\ViewController
546
  {
547
  $sorturl = add_query_arg('order', 'asc', $sorturl);
548
  }
549
- $output = '<a href="' . esc_url($sorturl) . '"><span>' . $title . '</span><span class="sorting-indicator '. $sorted . '">&nbsp;</span></a>';
550
  }
551
  else
552
  {
36
  parent::__construct();
37
  $this->setActions(); // possible actions for ROWS only..
38
 
39
+ // 2015: https://github.com/WordPress/WordPress-Coding-Standards/issues/426 !
40
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is not a form
41
  $this->currentPage = isset($_GET['paged']) ? intval($_GET['paged']) : 1;
42
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is not a form
43
+ $this->orderby = ( ! empty( $_GET['orderby'] ) ) ? $this->filterAllowedOrderBy(sanitize_text_field(wp_unslash($_GET['orderby']))) : 'id';
44
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is not a form
45
+ $this->order = ( ! empty($_GET['order'] ) ) ? sanitize_text_field( wp_unslash($_GET['order'])) : 'desc'; // If no order, default to asc
46
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is not a form
47
+ $this->search = (isset($_GET["s"]) && strlen($_GET["s"]) > 0) ? sanitize_text_field( wp_unslash($_GET['s'])) : false;
48
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is not a form
49
+ $this->show_hidden = isset($_GET['show_hidden']) ? sanitize_text_field(wp_unslash($_GET['show_hidden'])) : false;
50
 
51
  }
52
 
67
 
68
  public function action_refreshfolders()
69
  {
70
+ if (isset($_REQUEST['_wpnonce']) && wp_verify_nonce( sanitize_key($_REQUEST['_wpnonce']), 'refresh_folders'))
71
  {
72
  $otherMediaController = OtherMediaController::getInstance();
73
  $otherMediaController->refreshFolders(true);
212
 
213
  protected function getFilter() {
214
  $filter = array();
215
+
216
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is not a form
217
+ $search = (isset($_GET['s'])) ? sanitize_text_field(wp_unslash($_GET['s'])) : '';
218
+ if(strlen($search) > 0) {
219
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is not a form
220
+ $filter['path'] = (object)array("operator" => "like", "value" =>"'%" . esc_sql($search) . "%'");
221
  }
222
  return $filter;
223
  }
345
  $total_pages_before = '<span class="paging-input">';
346
  $total_pages_after = '</span></span>';
347
 
348
+ $current_url = esc_url(remove_query_arg( 'paged', $this->getPageURL())); // has url
349
 
350
+ $output = '<form method="GET" action="'. esc_attr($current_url) . '">'; //'<span class="pagination-links">';
351
+ $output .= '<span class="displaying-num">'. sprintf(esc_html__('%d Images', 'shortpixel-image-optimiser'), $this->total_items) . '</span>';
352
 
353
  if ( $disable_first ) {
354
  $page_links[] = '<span class="tablenav-pages-navspan button disabled" aria-hidden="true">&laquo;</span>';
356
  $page_links[] = sprintf(
357
  "<a class='first-page button' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
358
  esc_url( $current_url ),
359
+ esc_html__( 'First page' ),
360
  '&laquo;'
361
  );
362
  }
367
  $page_links[] = sprintf(
368
  "<a class='prev-page button' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
369
  esc_url( add_query_arg( 'paged', max( 1, $current - 1 ), $current_url ) ),
370
+ esc_html__( 'Previous page' ),
371
  '&lsaquo;'
372
  );
373
  }
374
 
375
  $html_current_page = sprintf(
376
  "%s<input class='current-page' id='current-page-selector' type='text' name='paged' value='%s' size='%d' aria-describedby='table-paging' /><span class='tablenav-paging-text'>",
377
+ '<label for="current-page-selector" class="screen-reader-text">' . esc_html__( 'Current Page' ) . '</label>',
378
  $current,
379
  strlen( $pages )
380
  );
472
  $classes = ($action['display'] == 'button') ? " button-smaller button-primary $actionName " : "$actionName";
473
  $link = ($action['type'] == 'js') ? 'javascript:' . $action['function'] : $action['function'];
474
 
475
+ // @todo Esc url is not successfull with JS links
476
  ?>
477
+ <a href="<?php echo $link ?>" class="<?php echo esc_attr($classes) ?>"><?php echo esc_html($action['text']) ?></a>
478
 
479
  <?php
480
  endforeach;
483
  }
484
 
485
 
486
+ // Used for row actions at the moment. Action under the image.
487
  protected function renderActions($actions, $item, $forceSingular = false)
488
  {
489
 
490
+
491
  foreach($actions as $index => $action)
492
  {
493
  $text = isset($action['text']) ? $action['text'] : '';
511
  $url = add_query_arg('type', $action['type'], $url);
512
  $class = (isset($action['class'])) ? $action['class'] : '';
513
 
 
514
  $link = '<a href="' . esc_url($url) . '" class="action-' . esc_attr($action_arg) . ' ' . esc_attr($class) . '">' . esc_html($text) . '</a>';
515
  }
516
 
557
  {
558
  $sorturl = add_query_arg('order', 'asc', $sorturl);
559
  }
560
+ $output = '<a href="' . esc_url($sorturl) . '"><span>' . esc_html($title) . '</span><span class="sorting-indicator '. esc_attr($sorted) . '">&nbsp;</span></a>';
561
  }
562
  else
563
  {
class/Helper/InstallHelper.php CHANGED
@@ -30,7 +30,6 @@ class InstallHelper
30
  \WPShortPixelSettings::onActivate();
31
  OptimizeController::resetQueues();
32
 
33
-
34
  $settings->currentVersion = SHORTPIXEL_IMAGE_OPTIMISER_VERSION;
35
  }
36
 
@@ -79,7 +78,8 @@ class InstallHelper
79
  $env = \wpSPIO()->env();
80
  $settings = \wpSPIO()->settings();
81
 
82
- $nonce = $_POST['tools-nonce'];
 
83
  if ( ! wp_verify_nonce( $nonce, 'remove-all' ) ) {
84
  wp_nonce_ays( '' );
85
  }
@@ -107,16 +107,17 @@ class InstallHelper
107
 
108
  public static function deactivateConflictingPlugin()
109
  {
110
- if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'sp_deactivate_plugin_nonce' ) ) {
111
  wp_nonce_ays( 'Nononce' );
112
  }
113
 
114
  $referrer_url = wp_get_referer();
115
  $conflict = \ShortPixelTools::getConflictingPlugins();
116
  $url = wp_get_referer();
117
- $plugin = sanitize_text_field($_GET['plugin']); // our target.
118
 
119
- deactivate_plugins($plugin);
 
120
 
121
  wp_safe_redirect($url);
122
  die();
30
  \WPShortPixelSettings::onActivate();
31
  OptimizeController::resetQueues();
32
 
 
33
  $settings->currentVersion = SHORTPIXEL_IMAGE_OPTIMISER_VERSION;
34
  }
35
 
78
  $env = \wpSPIO()->env();
79
  $settings = \wpSPIO()->settings();
80
 
81
+
82
+ $nonce = (isset($_POST['tools-nonce'])) ? sanitize_key($_POST['tools-nonce']) : null;
83
  if ( ! wp_verify_nonce( $nonce, 'remove-all' ) ) {
84
  wp_nonce_ays( '' );
85
  }
107
 
108
  public static function deactivateConflictingPlugin()
109
  {
110
+ if ( ! isset($_GET['_wpnonce']) || ! wp_verify_nonce( sanitize_key($_GET['_wpnonce']), 'sp_deactivate_plugin_nonce' ) ) {
111
  wp_nonce_ays( 'Nononce' );
112
  }
113
 
114
  $referrer_url = wp_get_referer();
115
  $conflict = \ShortPixelTools::getConflictingPlugins();
116
  $url = wp_get_referer();
117
+ $plugin = (isset($_GET['plugin'])) ? sanitize_text_field(wp_unslash($_GET['plugin'])) : null; // our target.
118
 
119
+ if (! is_null($plugin))
120
+ deactivate_plugins($plugin);
121
 
122
  wp_safe_redirect($url);
123
  die();
class/Helper/UiHelper.php CHANGED
@@ -37,7 +37,7 @@ class UiHelper
37
  foreach($actions as $actionName => $actionData)
38
  {
39
  $link = ($actionData['type'] == 'js') ? 'javascript:' . $actionData['function'] : $actionData['function'];
40
- $output .= "<a href='" . $link . "' class='$actionName' >" . $actionData['text'] . "</a>";
41
 
42
  }
43
 
@@ -115,7 +115,6 @@ class UiHelper
115
 
116
  }
117
 
118
-
119
  if (count($improvs) > 0)
120
  {
121
  $output .= "<div class='thumb-wrapper'>";
@@ -154,7 +153,7 @@ class UiHelper
154
  }
155
  if ($imageObj->isOptimized() && $imageObj->isProcessable())
156
  {
157
- $optimizable = $imageObj->getOptimizeURLS();
158
  // Todo check if Webp / Acif is active, check for unoptimized items
159
  $processWebp = ($imageObj->isProcessableFileType('webp')) ? true : false;
160
  $processAvif = ($imageObj->isProcessableFileType('avif')) ? true : false;
@@ -244,8 +243,7 @@ class UiHelper
244
 
245
  if ($mediaItem->isOptimized())
246
  {
247
- $optimizable = $mediaItem->getOptimizeURLS();
248
- //$webp = $mediaItem->
249
 
250
  if ($mediaItem->isProcessable() && ! $mediaItem->isOptimizePrevented())
251
  {
@@ -256,8 +254,8 @@ class UiHelper
256
  }
257
  else
258
  {
259
- $optimizableWebp = $mediaItem->isProcessableFileType('webp') ? count($mediaItem->getOptimizeFileType('webp')) : 0;
260
- $optimizableAvif = $mediaItem->isProcessableFileType('avif') ? count($mediaItem->getOptimizeFileType('avif')) : 0;
261
 
262
  if ($optimizableWebp > 0 && $optimizableAvif > 0)
263
  $text = sprintf(__('Optimize %s webps and %s avif','shortpixel-image-optimiser'),$optimizableWebp, $optimizableAvif);
@@ -390,11 +388,10 @@ class UiHelper
390
  {
391
  $text = UiHelper::renderSuccessText($mediaItem);
392
  }
393
- elseif (! $mediaItem->isProcessable(true) && ! $mediaItem->isOptimized())
394
  {
395
  $text = __('Not Processable: ','shortpixel_image_optimiser');
396
  $text .= $mediaItem->getProcessableReason();
397
-
398
  }
399
  elseif (! $mediaItem->exists())
400
  {
@@ -413,9 +410,35 @@ class UiHelper
413
  {
414
 
415
  $retry = self::getAction('retry', $mediaItem->get('id'));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
416
  $text .= "<div class='shortpixel-image-error'>" . esc_html($mediaItem->isOptimizePrevented());
417
  $text .= "<span class='shortpixel-error-reset'>" . sprintf(__('After you have fixed this issue, you can %s click here to retry %s', 'shortpixel-image-optimiser'), '<a href="javascript:' . $retry['function'] . '">', '</a>');
 
418
  $text .= '</div>';
 
 
 
 
 
 
 
 
 
 
419
  }
420
 
421
  return $text;
@@ -447,6 +470,12 @@ class UiHelper
447
  $action['text'] = __('Retry', 'shortpixel-image-optimiser') ;
448
  $action['display'] = 'button';
449
  break;
 
 
 
 
 
 
450
 
451
  case 'restore':
452
  $action['function'] = 'window.ShortPixelProcessor.screen.RestoreItem(' . $id . ');';
@@ -488,7 +517,7 @@ class UiHelper
488
  break;
489
 
490
  case 'extendquota':
491
- $action['function'] = 'https://shortpixel.com/login'. $keyControl->getKeyForDisplay();
492
  $action['type'] = 'button';
493
  $action['text'] = __('Extend Quota','shortpixel-image-optimiser');
494
  $action['display'] = 'button';
37
  foreach($actions as $actionName => $actionData)
38
  {
39
  $link = ($actionData['type'] == 'js') ? 'javascript:' . $actionData['function'] : $actionData['function'];
40
+ $output .= "<a href='" . $link . "' class='" . esc_attr($actionName) . "' >" . esc_html($actionData['text']) . "</a>";
41
 
42
  }
43
 
115
 
116
  }
117
 
 
118
  if (count($improvs) > 0)
119
  {
120
  $output .= "<div class='thumb-wrapper'>";
153
  }
154
  if ($imageObj->isOptimized() && $imageObj->isProcessable())
155
  {
156
+ $optimizable = $imageObj->getOptimizeURLS(true);
157
  // Todo check if Webp / Acif is active, check for unoptimized items
158
  $processWebp = ($imageObj->isProcessableFileType('webp')) ? true : false;
159
  $processAvif = ($imageObj->isProcessableFileType('avif')) ? true : false;
243
 
244
  if ($mediaItem->isOptimized())
245
  {
246
+ $optimizable = $mediaItem->getOptimizeURLS(true);
 
247
 
248
  if ($mediaItem->isProcessable() && ! $mediaItem->isOptimizePrevented())
249
  {
254
  }
255
  else
256
  {
257
+ $optimizableWebp = $mediaItem->isProcessableFileType('webp') ? count($mediaItem->getOptimizeFileType('webp', true)) : 0;
258
+ $optimizableAvif = $mediaItem->isProcessableFileType('avif') ? count($mediaItem->getOptimizeFileType('avif', true)) : 0;
259
 
260
  if ($optimizableWebp > 0 && $optimizableAvif > 0)
261
  $text = sprintf(__('Optimize %s webps and %s avif','shortpixel-image-optimiser'),$optimizableWebp, $optimizableAvif);
388
  {
389
  $text = UiHelper::renderSuccessText($mediaItem);
390
  }
391
+ elseif (! $mediaItem->isProcessable() && ! $mediaItem->isOptimized())
392
  {
393
  $text = __('Not Processable: ','shortpixel_image_optimiser');
394
  $text .= $mediaItem->getProcessableReason();
 
395
  }
396
  elseif (! $mediaItem->exists())
397
  {
410
  {
411
 
412
  $retry = self::getAction('retry', $mediaItem->get('id'));
413
+
414
+
415
+ $redo_legacy = false;
416
+ $was_converted = get_post_meta($mediaItem->get('id'), '_shortpixel_was_converted', true);
417
+ $updateTs = 1656892800; // July 4th 2022 - 00:00 GMT
418
+
419
+ if ($was_converted < $updateTs)
420
+ {
421
+ $meta = $mediaItem->getWPMetaData();
422
+ if (is_array($meta) && isset($meta['ShortPixel']))
423
+ {
424
+ $redo_legacy = self::getAction('redo_legacy', $mediaItem->get('id'));
425
+ }
426
+ }
427
+
428
  $text .= "<div class='shortpixel-image-error'>" . esc_html($mediaItem->isOptimizePrevented());
429
  $text .= "<span class='shortpixel-error-reset'>" . sprintf(__('After you have fixed this issue, you can %s click here to retry %s', 'shortpixel-image-optimiser'), '<a href="javascript:' . $retry['function'] . '">', '</a>');
430
+
431
  $text .= '</div>';
432
+
433
+
434
+ if ($redo_legacy !== false)
435
+ {
436
+ $text .= "<div class='shortpixel-image-error'><span class='shortpixel-error-reset'>";
437
+
438
+ $text .= sprintf(esc_html__('It seems you have older converted legacy data, which might cause this issue. You can try to %s %s %s . If nothing changes, this is not the cause. ','shortpixel-image-optimiser'), '<a href="javascript:' . $redo_legacy['function'] . '">', $redo_legacy['text'], '</a>');
439
+ $text .= "</span></div>";
440
+ }
441
+
442
  }
443
 
444
  return $text;
470
  $action['text'] = __('Retry', 'shortpixel-image-optimiser') ;
471
  $action['display'] = 'button';
472
  break;
473
+ case 'redo_legacy':
474
+ $action['function'] = 'window.ShortPixelProcessor.screen.RedoLegacy(' . $id . ');';
475
+ $action['type'] = 'js';
476
+ $action['text'] = __('Redo Conversion', 'shortpixel-image-optimiser') ;
477
+ $action['display'] = 'button';
478
+ break;
479
 
480
  case 'restore':
481
  $action['function'] = 'window.ShortPixelProcessor.screen.RestoreItem(' . $id . ');';
517
  break;
518
 
519
  case 'extendquota':
520
+ $action['function'] = 'https://shortpixel.com/login/'. $keyControl->getKeyForDisplay();
521
  $action['type'] = 'button';
522
  $action['text'] = __('Extend Quota','shortpixel-image-optimiser');
523
  $action['display'] = 'button';
class/Model/ApiKeyModel.php CHANGED
@@ -294,7 +294,7 @@ class ApiKeyModel extends \ShortPixel\Model
294
  if(! \wpSPIO()->env()->is_ajaxcall && !$this->redirectedSettings && !$this->verifiedKey && (!function_exists("is_multisite") || ! is_multisite())) {
295
  $this->redirectedSettings = 1;
296
  $this->update();
297
- wp_redirect(admin_url("options-general.php?page=wp-shortpixel-settings"));
298
  exit();
299
  }
300
 
294
  if(! \wpSPIO()->env()->is_ajaxcall && !$this->redirectedSettings && !$this->verifiedKey && (!function_exists("is_multisite") || ! is_multisite())) {
295
  $this->redirectedSettings = 1;
296
  $this->update();
297
+ wp_safe_redirect(admin_url("options-general.php?page=wp-shortpixel-settings"));
298
  exit();
299
  }
300
 
class/Model/EnvironmentModel.php CHANGED
@@ -30,6 +30,7 @@ class EnvironmentModel extends \ShortPixel\Model
30
  private $screen_is_set = false;
31
  public $is_screen_to_use = false; // where shortpixel optimizer loads
32
  public $is_our_screen = false; // where shortpixel hooks in more complicated functions.
 
33
  public $is_bulk_page = false; // ShortPixel bulk screen.
34
  public $screen_id = false;
35
 
@@ -67,7 +68,7 @@ class EnvironmentModel extends \ShortPixel\Model
67
  {
68
  if (count($this->disabled_functions) == 0)
69
  {
70
- $disabled = ini_get('disable_functions');
71
  $this->disabled_functions = explode(',', $disabled);
72
  }
73
 
@@ -129,8 +130,8 @@ class EnvironmentModel extends \ShortPixel\Model
129
 
130
  private function setServer()
131
  {
132
- $this->is_nginx = strpos(strtolower($_SERVER["SERVER_SOFTWARE"]), 'nginx') !== false ? true : false;
133
- $this->is_apache = strpos(strtolower($_SERVER["SERVER_SOFTWARE"]), 'apache') !== false ? true : false;
134
  $this->is_gd_installed = function_exists('imagecreatefrompng') && function_exists('imagejpeg');
135
  $this->is_curl_installed = function_exists('curl_init');
136
  }
@@ -209,6 +210,10 @@ class EnvironmentModel extends \ShortPixel\Model
209
  if ($screen->id == 'media_page_wp-short-pixel-bulk')
210
  $this->is_bulk_page = true;
211
  }
 
 
 
 
212
 
213
  $this->screen_is_set = true;
214
  }
30
  private $screen_is_set = false;
31
  public $is_screen_to_use = false; // where shortpixel optimizer loads
32
  public $is_our_screen = false; // where shortpixel hooks in more complicated functions.
33
+ public $is_gutenberg_editor = false;
34
  public $is_bulk_page = false; // ShortPixel bulk screen.
35
  public $screen_id = false;
36
 
68
  {
69
  if (count($this->disabled_functions) == 0)
70
  {
71
+ $disabled = ini_get('disable_functions');
72
  $this->disabled_functions = explode(',', $disabled);
73
  }
74
 
130
 
131
  private function setServer()
132
  {
133
+ $this->is_nginx = ! empty($_SERVER["SERVER_SOFTWARE"]) && strpos(strtolower(wp_unslash($_SERVER["SERVER_SOFTWARE"])), 'nginx') !== false ? true : false;
134
+ $this->is_apache = ! empty($_SERVER["SERVER_SOFTWARE"]) && strpos(strtolower(wp_unslash($_SERVER["SERVER_SOFTWARE"])), 'apache') !== false ? true : false;
135
  $this->is_gd_installed = function_exists('imagecreatefrompng') && function_exists('imagejpeg');
136
  $this->is_curl_installed = function_exists('curl_init');
137
  }
210
  if ($screen->id == 'media_page_wp-short-pixel-bulk')
211
  $this->is_bulk_page = true;
212
  }
213
+ elseif (is_object($screen) && method_exists( $screen, 'is_block_editor' ) && $screen->is_block_editor() ) {
214
+ $this->is_screen_to_use = true;
215
+ $this->is_gutenberg_editor = true;
216
+ }
217
 
218
  $this->screen_is_set = true;
219
  }
class/Model/File/DirectoryModel.php CHANGED
@@ -155,7 +155,8 @@ class DirectoryModel extends \ShortPixel\Model
155
  */
156
  public function getRelativePath()
157
  {
158
- $upload_dir = wp_upload_dir(null, false);
 
159
 
160
  $install_dir = get_home_path();
161
  if($install_dir == '/') {
@@ -451,7 +452,7 @@ class DirectoryModel extends \ShortPixel\Model
451
  $size = 0;
452
  $files = $this->getFiles();
453
 
454
- // GetFiles can return Boolean false on missing directory.
455
  if (! is_array($files))
456
  {
457
  return $size;
155
  */
156
  public function getRelativePath()
157
  {
158
+ // not used anywhere in directory.
159
+ // $upload_dir = wp_upload_dir(null, false);
160
 
161
  $install_dir = get_home_path();
162
  if($install_dir == '/') {
452
  $size = 0;
453
  $files = $this->getFiles();
454
 
455
+ // GetFiles can return Boolean false on missing directory.
456
  if (! is_array($files))
457
  {
458
  return $size;
class/Model/File/FileModel.php CHANGED
@@ -94,7 +94,7 @@ class FileModel extends \ShortPixel\Model
94
  $this->exists = (@file_exists($this->fullpath) && is_file($this->fullpath));
95
  }
96
 
97
- $this->exists = apply_filters('shortpixel_image_exists', $this->exists, $this->fullpath, $this);
98
  $this->exists = apply_filters('shortpixel/file/exists', $this->exists, $this->fullpath, $this);
99
  return $this->exists;
100
  }
@@ -535,8 +535,10 @@ class FileModel extends \ShortPixel\Model
535
 
536
  $this->is_virtual = true;
537
 
 
538
  $path = apply_filters('shortpixel/image/urltopath', false, $url);
539
- if ($path !== false)
 
540
  {
541
  $this->exists = true;
542
  $this->is_readable = true;
94
  $this->exists = (@file_exists($this->fullpath) && is_file($this->fullpath));
95
  }
96
 
97
+ $this->exists = apply_filters('shortpixel_image_exists', $this->exists, $this->fullpath, $this); //legacy
98
  $this->exists = apply_filters('shortpixel/file/exists', $this->exists, $this->fullpath, $this);
99
  return $this->exists;
100
  }
535
 
536
  $this->is_virtual = true;
537
 
538
+
539
  $path = apply_filters('shortpixel/image/urltopath', false, $url);
540
+
541
+ if ($path !== false)
542
  {
543
  $this->exists = true;
544
  $this->is_readable = true;
class/Model/Image/ImageModel.php CHANGED
@@ -95,7 +95,7 @@ abstract class ImageModel extends \ShortPixel\Model\File\FileModel
95
  $this->width = false; // to prevent is_null check on get to loop if something is off.
96
  $this->height = false;
97
 
98
- if (! $this->isExtensionExcluded() && $this->isImage() && $this->is_readable() && ! $this->is_virtual())
99
  {
100
  list($width, $height) = @getimagesize($this->getFullPath());
101
  if ($width)
@@ -137,7 +137,8 @@ abstract class ImageModel extends \ShortPixel\Model\File\FileModel
137
  if ($type == 'avif' && ! $settings->createAvif)
138
  return false;
139
 
140
- $files = $this->getOptimizeFileType($type);
 
141
 
142
  if (count($files) > 0)
143
  return true;
@@ -296,7 +297,7 @@ abstract class ImageModel extends \ShortPixel\Model\File\FileModel
296
  {
297
  $fs = \wpSPIO()->filesystem();
298
 
299
- if (! is_null($this->getMeta($type)))
300
  {
301
  $filepath = $this->getFileDir() . $this->getMeta($type);
302
  $file = $fs->getFile($filepath);
95
  $this->width = false; // to prevent is_null check on get to loop if something is off.
96
  $this->height = false;
97
 
98
+ if (! $this->isExtensionExcluded() && $this->isImage() && $this->is_readable() && ! $this->is_virtual() )
99
  {
100
  list($width, $height) = @getimagesize($this->getFullPath());
101
  if ($width)
137
  if ($type == 'avif' && ! $settings->createAvif)
138
  return false;
139
 
140
+ // true, will only return paths ( = lighter )
141
+ $files = $this->getOptimizeFileType($type, true);
142
 
143
  if (count($files) > 0)
144
  return true;
297
  {
298
  $fs = \wpSPIO()->filesystem();
299
 
300
+ if (! is_null($this->getMeta($type)))
301
  {
302
  $filepath = $this->getFileDir() . $this->getMeta($type);
303
  $file = $fs->getFile($filepath);
class/Model/Image/MediaLibraryModel.php CHANGED
@@ -41,6 +41,7 @@ class MediaLibraryModel extends \ShortPixel\Model\Image\MediaLibraryThumbnailMod
41
 
42
  parent::__construct($path, $post_id, null);
43
 
 
44
  // WP 5.3 and higher. Check for original file.
45
  if (function_exists('wp_get_original_image_path'))
46
  {
@@ -71,32 +72,40 @@ class MediaLibraryModel extends \ShortPixel\Model\Image\MediaLibraryThumbnailMod
71
  }
72
 
73
 
74
- public function getOptimizeUrls()
 
75
  {
76
  $settings = \wpSPIO()->settings();
77
 
78
- $url = $this->getURL();
 
79
 
80
- if (! $url) // If the whole image URL can't be found
81
- {
82
- return array();
83
- }
 
 
 
 
 
 
84
 
85
  $urls = array();
86
  if ($this->isProcessable(true))
87
- $urls = array($url);
88
- else {
89
- }
90
 
91
  if ($this->isScaled())
92
  {
93
- $urls = array_merge($urls, $this->original_file->getOptimizeUrls());
94
  }
95
 
96
  foreach($this->thumbnails as $thumbObj)
97
  {
98
  if($thumbObj->isThumbnailProcessable())
99
- $urls = array_merge($urls, $thumbObj->getOptimizeUrls());
100
  }
101
 
102
  // @todo Check Retina's
@@ -105,7 +114,7 @@ class MediaLibraryModel extends \ShortPixel\Model\Image\MediaLibraryThumbnailMod
105
 
106
  foreach($this->retinas as $retinaObj)
107
  {
108
- $urls = array_merge($urls, $retinaObj->getOptimizeUrls());
109
  }
110
  }
111
  $urls = array_values(array_unique($urls));
@@ -113,14 +122,17 @@ class MediaLibraryModel extends \ShortPixel\Model\Image\MediaLibraryThumbnailMod
113
  }
114
 
115
  // Try to get the URL via WordPress
 
116
  public function getURL()
117
  {
118
  $url = $this->fs()->checkURL(wp_get_attachment_url($this->id));
119
  return $url;
120
  }
121
 
122
- /** Get FileTypes that might be optimized. Checking for setting should go via isProcessableFileType! */
123
- public function getOptimizeFileType($type = 'webp')
 
 
124
  {
125
  if ($type == 'webp')
126
  {
@@ -141,21 +153,40 @@ class MediaLibraryModel extends \ShortPixel\Model\Image\MediaLibraryThumbnailMod
141
  {
142
  if (parent::getOptimizeFileType($type))
143
  {
144
- $toOptimize[] = $this->getURL(); // $fs->pathToUrl($this);
145
- }
146
-
147
- }
 
 
 
148
  }
149
  if ($this->isScaled() ) // scaled image
150
  {
151
  if ($this->original_file->getOptimizeFileType($type) )
152
- $toOptimize[] = $this->original_file->getURL(); //$fs->pathToUrl($this->original_file);
 
 
 
 
 
 
 
 
153
  }
154
 
155
  foreach($this->thumbnails as $thumbName => $thumbObj)
156
  {
157
  if ($thumbObj->getOptimizeFileType($type))
 
 
 
 
 
 
158
  $toOptimize[] = $thumbObj->getURL(); //$fs->pathToUrl($thumbObj);
 
 
159
  }
160
 
161
  return array_values(array_unique($toOptimize));
@@ -367,23 +398,12 @@ class MediaLibraryModel extends \ShortPixel\Model\Image\MediaLibraryThumbnailMod
367
 
368
  }
369
 
370
- /* Sanity check in process. Should only be called upon special request, or with single image displays. Should check and recheck stats, thumbs, unlistedthumbs and all assumptions of data that might corrupt or change outside of this plugin */
371
- public function reAcquire()
372
- {
373
- $this->addUnlisted();
374
- //$this->reCheckThumbnails();
375
- if (\wpSPIO()->settings()->optimizeRetina)
376
- $this->retinas = $this->getRetinas();
377
-
378
- $this->webps = $this->getWebps();
379
-
380
- }
381
-
382
  public function handleOptimized($tempFiles)
383
  {
384
  $return = true;
385
  $wpmeta = wp_get_attachment_metadata($this->get('id'));
386
 
 
387
  if (! $this->isOptimized() && isset($tempFiles[$this->getFileName()]) ) // main file might not be contained in results
388
  {
389
  if ($this->getExtension() == 'heic')
@@ -431,11 +451,13 @@ class MediaLibraryModel extends \ShortPixel\Model\Image\MediaLibraryThumbnailMod
431
  $thumbnail->handleOptimizedFileType($tempFiles); // check for webps /etc
432
 
433
  if ($thumbnail->isOptimized())
434
- continue;
435
-
 
436
  if (!$thumbnail->isProcessable())
 
437
  continue; // when excluded.
438
-
439
  $filebase = $thumbnail->getFileBase();
440
  $result = false;
441
 
@@ -451,16 +473,20 @@ class MediaLibraryModel extends \ShortPixel\Model\Image\MediaLibraryThumbnailMod
451
  $result = $thumbnail->handleOptimized($tempFiles);
452
  }
453
 
454
- // Always update the WP meta.
455
- $size = $thumbnail->get('size');
456
- if ($thumbnail->getMeta('resize') == true)
457
  {
458
 
459
- $wpmeta['sizes'][$size]['width'] = $thumbnail->get('width');
460
- $wpmeta['sizes'][$size]['height'] = $thumbnail->get('height');
461
- }
 
 
 
 
 
462
 
463
- $wpmeta['sizes'][$size]['filesize'] = $thumbnail->getFileSize();
464
 
465
  if ($result)
466
  {
@@ -782,34 +808,36 @@ class MediaLibraryModel extends \ShortPixel\Model\Image\MediaLibraryThumbnailMod
782
  $extra_info = json_decode($record->extra_info);
783
 
784
  // @todo Extra info should probably be stored as JSON?
785
- foreach($extra_info as $name => $val)
786
- {
787
- $data->$name = $val;
788
- }
789
-
790
- if ($record->parent == 0)
791
  {
792
- // Database ID should probably also be stored for the thumbnails, so updating / insert into the database will be easier. We have a free primary key, so why not use it?
793
- $metadata->image_meta = $data;
794
- }
795
- elseif($record->parent > 0) // Thumbnails
796
- {
797
- switch($record->image_type)
798
- {
799
- case self::IMAGE_TYPE_THUMB:
800
- $metadata->thumbnails[$record->size] = $data;
801
- break;
802
- case self::IMAGE_TYPE_RETINA:
803
- $metadata->retinas[$record->size] = $data;
804
- break;
805
- case self::IMAGE_TYPE_ORIGINAL:
806
- $metadata->original_file = $data;
807
- break;
808
- }
809
 
810
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
811
 
812
- }
 
 
813
 
814
  return $metadata;
815
  }
@@ -1154,6 +1182,12 @@ class MediaLibraryModel extends \ShortPixel\Model\Image\MediaLibraryThumbnailMod
1154
  return $bool;
1155
  }
1156
 
 
 
 
 
 
 
1157
  if (! $bool) // if parent is not processable, check if thumbnails are, can still have a work to do.
1158
  {
1159
 
@@ -1363,6 +1397,11 @@ class MediaLibraryModel extends \ShortPixel\Model\Image\MediaLibraryThumbnailMod
1363
  //$meta = $meta? $meta : wp_get_attachment_metadata($ID);
1364
  $width = $this->get('width');
1365
  $height = $this->get('height');
 
 
 
 
 
1366
  if( $width && $height
1367
  && $this->isProcessableSize($width, $height, $item["value"]) === false){
1368
  $this->processable_status = self::P_EXCLUDE_SIZE;
@@ -1550,6 +1589,7 @@ class MediaLibraryModel extends \ShortPixel\Model\Image\MediaLibraryThumbnailMod
1550
  // ** Warning - This will also reset metadata
1551
  $bool = parent::restore();
1552
 
 
1553
  if ($is_resized)
1554
  {
1555
  $wpmeta['width'] = $this->get('width');
@@ -1582,7 +1622,9 @@ class MediaLibraryModel extends \ShortPixel\Model\Image\MediaLibraryThumbnailMod
1582
  $filebase = $thumbObj->getFileBase();
1583
  $is_resized = $thumbObj->getMeta('resize');
1584
  $size = $thumbObj->get('size');
 
1585
 
 
1586
  if (isset($restored[$filebase]))
1587
  {
1588
  $bool = true; // this filebase already restored. In case of duplicate sizes.
@@ -1593,13 +1635,17 @@ class MediaLibraryModel extends \ShortPixel\Model\Image\MediaLibraryThumbnailMod
1593
  $bool = $thumbObj->restore(); // resets metadata
1594
  }
1595
 
1596
- if ($is_resized)
1597
  {
1598
- $wpmeta['sizes'][$size]['width'] = $thumbObj->get('width');
1599
- $wpmeta['sizes'][$size]['height'] = $thumbObj->get('height');
1600
- }
1601
 
1602
- $wpmeta['sizes'][$size]['filesize'] = $thumbObj->getFileSize();
 
 
 
 
 
 
 
1603
 
1604
  if (! $bool)
1605
  {
@@ -1863,14 +1909,14 @@ class MediaLibraryModel extends \ShortPixel\Model\Image\MediaLibraryThumbnailMod
1863
  return false;
1864
  }
1865
 
1866
-
1867
  $data = $metadata['ShortPixel'];
1868
 
1869
  if (count($data) == 0) // This can happen. Empty array is still nothing to convert.
1870
  return false;
1871
 
1872
  // Waiting for processing is a state where it's not optimized, or should be.
1873
- if (count($data) == 1 && isset($data['WaitingProcessing']))
 
1874
  {
1875
  return false;
1876
  }
@@ -1879,8 +1925,21 @@ class MediaLibraryModel extends \ShortPixel\Model\Image\MediaLibraryThumbnailMod
1879
  $was_converted = get_post_meta($this->id, '_shortpixel_was_converted', true);
1880
  if ($was_converted == true || is_numeric($was_converted))
1881
  {
1882
- Log::addDebug('No SPIO5 metadata, but this item was converted, not converting again');
1883
- return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
1884
  }
1885
 
1886
  $quotaController = QuotaController::getInstance();
@@ -1891,7 +1950,7 @@ class MediaLibraryModel extends \ShortPixel\Model\Image\MediaLibraryThumbnailMod
1891
  }
1892
 
1893
  Log::addDebug("Conversion of legacy: ", array($metadata));
1894
- // echo "*** EXPORT: "; var_export($metadata); echo " *** ";
1895
  $type = isset($data['type']) ? $this->legacyConvertType($data['type']) : '';
1896
 
1897
  $improvement = (isset($metadata['ShortPixelImprovement']) && is_numeric($metadata['ShortPixelImprovement']) && $metadata['ShortPixelImprovement'] > 0) ? $metadata['ShortPixelImprovement'] : 0;
@@ -2091,12 +2150,15 @@ class MediaLibraryModel extends \ShortPixel\Model\Image\MediaLibraryThumbnailMod
2091
  {
2092
  return $fileType->getFileName();
2093
  }
 
2094
  $env = \wpSPIO()->env();
2095
  $fs = \wpSPIO()->filesystem();
2096
 
2097
  // try the whole thing, but fetching remote URLS, test if really S3 not in case something went wrong with is_virtual, or it's just something messed up.
2098
  if ($fileObj->is_virtual() && $env->plugin_active('s3-offload') )
2099
  {
 
 
2100
  if ($type == 'webp')
2101
  {
2102
  $is_double = \wpSPIO()->env()->useDoubleWebpExtension();
@@ -2134,7 +2196,7 @@ class MediaLibraryModel extends \ShortPixel\Model\Image\MediaLibraryThumbnailMod
2134
  }
2135
  else
2136
  {
2137
- $url_exists = $fs->getFile($double_url);
2138
  if ($url_exists === true)
2139
  return $double_filename;
2140
  }
@@ -2334,6 +2396,10 @@ class MediaLibraryModel extends \ShortPixel\Model\Image\MediaLibraryThumbnailMod
2334
  $added = false;
2335
  foreach($unlisted as $unName)
2336
  {
 
 
 
 
2337
  $thumbObj = $this->getThumbnailModel($path . $unName, $unName);
2338
  if ($thumbObj->getExtension() == 'webp' || $thumbObj->getExtension() == 'avif') // ignore webp/avif files.
2339
  {
@@ -2354,8 +2420,8 @@ class MediaLibraryModel extends \ShortPixel\Model\Image\MediaLibraryThumbnailMod
2354
  }
2355
  }
2356
 
2357
- if ($added)
2358
- $this->saveMeta(); // Save it when we are adding images.
2359
 
2360
  self::$unlistedChecked[] = $this->get('id');
2361
  }
41
 
42
  parent::__construct($path, $post_id, null);
43
 
44
+
45
  // WP 5.3 and higher. Check for original file.
46
  if (function_exists('wp_get_original_image_path'))
47
  {
72
  }
73
 
74
 
75
+ // Path will only return the filepath. For reasons, see getOptimizeFileType
76
+ public function getOptimizeUrls($get_path = false)
77
  {
78
  $settings = \wpSPIO()->settings();
79
 
80
+ if (true === $get_path)
81
+ {
82
 
83
+ $url = $this->getFullPath();
84
+ }
85
+ else{
86
+ $url = $this->getURL();
87
+ }
88
+
89
+ if (! $url) // If the whole image URL can't be found
90
+ {
91
+ return array();
92
+ }
93
 
94
  $urls = array();
95
  if ($this->isProcessable(true))
96
+ {
97
+ $urls = array($url);
98
+ }
99
 
100
  if ($this->isScaled())
101
  {
102
+ $urls = array_merge($urls, $this->original_file->getOptimizeUrls($get_path));
103
  }
104
 
105
  foreach($this->thumbnails as $thumbObj)
106
  {
107
  if($thumbObj->isThumbnailProcessable())
108
+ $urls = array_merge($urls, $thumbObj->getOptimizeUrls($get_path));
109
  }
110
 
111
  // @todo Check Retina's
114
 
115
  foreach($this->retinas as $retinaObj)
116
  {
117
+ $urls = array_merge($urls, $retinaObj->getOptimizeUrls($get_path));
118
  }
119
  }
120
  $urls = array_values(array_unique($urls));
122
  }
123
 
124
  // Try to get the URL via WordPress
125
+ // This is now officially a heavy function. Take times, other plugins (like s3) might really delay it
126
  public function getURL()
127
  {
128
  $url = $this->fs()->checkURL(wp_get_attachment_url($this->id));
129
  return $url;
130
  }
131
 
132
+ /** Get FileTypes that might be optimized. Checking for setting should go via isProcessableFileType!
133
+ * Get path will return the filepath of said files. This is not useful, except for -checking- if it's processable via isProcessableFileType . GetURL can potentially hit performance, and we don't need it in that case.
134
+ */
135
+ public function getOptimizeFileType($type = 'webp', $get_path = false)
136
  {
137
  if ($type == 'webp')
138
  {
153
  {
154
  if (parent::getOptimizeFileType($type))
155
  {
156
+ if (true === $get_path) {
157
+ $toOptimize[] = $this->getFullPath();
158
+ } else {
159
+ $toOptimize[] = $this->getURL(); // $fs->pathToUrl($this);
160
+ }
161
+ }
162
+ }
163
  }
164
  if ($this->isScaled() ) // scaled image
165
  {
166
  if ($this->original_file->getOptimizeFileType($type) )
167
+ {
168
+ if (true === $get_path)
169
+ {
170
+ $toOptimize[] = $this->original_file->getFullPath();
171
+ }
172
+ else {
173
+ $toOptimize[] = $this->original_file->getURL();
174
+ }
175
+ }
176
  }
177
 
178
  foreach($this->thumbnails as $thumbName => $thumbObj)
179
  {
180
  if ($thumbObj->getOptimizeFileType($type))
181
+ {
182
+ if (true === $get_path)
183
+ {
184
+ $toOptimize[] = $thumbObj->getFullPath();
185
+ }
186
+ else{
187
  $toOptimize[] = $thumbObj->getURL(); //$fs->pathToUrl($thumbObj);
188
+ }
189
+ }
190
  }
191
 
192
  return array_values(array_unique($toOptimize));
398
 
399
  }
400
 
 
 
 
 
 
 
 
 
 
 
 
 
401
  public function handleOptimized($tempFiles)
402
  {
403
  $return = true;
404
  $wpmeta = wp_get_attachment_metadata($this->get('id'));
405
 
406
+
407
  if (! $this->isOptimized() && isset($tempFiles[$this->getFileName()]) ) // main file might not be contained in results
408
  {
409
  if ($this->getExtension() == 'heic')
451
  $thumbnail->handleOptimizedFileType($tempFiles); // check for webps /etc
452
 
453
  if ($thumbnail->isOptimized())
454
+ {
455
+ continue;
456
+ }
457
  if (!$thumbnail->isProcessable())
458
+ {
459
  continue; // when excluded.
460
+ }
461
  $filebase = $thumbnail->getFileBase();
462
  $result = false;
463
 
473
  $result = $thumbnail->handleOptimized($tempFiles);
474
  }
475
 
476
+ // Always update the WP meta - except for unlisted files.
477
+ if ($thumbnail->getMeta('file') === null)
 
478
  {
479
 
480
+ $size = $thumbnail->get('size');
481
+ if ($thumbnail->getMeta('resize') == true)
482
+ {
483
+ $wpmeta['sizes'][$size]['width'] = $thumbnail->get('width');
484
+ $wpmeta['sizes'][$size]['height'] = $thumbnail->get('height');
485
+ }
486
+
487
+ $wpmeta['sizes'][$size]['filesize'] = $thumbnail->getFileSize();
488
 
489
+ }
490
 
491
  if ($result)
492
  {
808
  $extra_info = json_decode($record->extra_info);
809
 
810
  // @todo Extra info should probably be stored as JSON?
811
+ if (! is_null($extra_info))
 
 
 
 
 
812
  {
813
+ foreach($extra_info as $name => $val)
814
+ {
815
+ $data->$name = $val;
816
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
817
 
818
+ if ($record->parent == 0)
819
+ {
820
+ // Database ID should probably also be stored for the thumbnails, so updating / insert into the database will be easier. We have a free primary key, so why not use it?
821
+ $metadata->image_meta = $data;
822
+ }
823
+ elseif($record->parent > 0) // Thumbnails
824
+ {
825
+ switch($record->image_type)
826
+ {
827
+ case self::IMAGE_TYPE_THUMB:
828
+ $metadata->thumbnails[$record->size] = $data;
829
+ break;
830
+ case self::IMAGE_TYPE_RETINA:
831
+ $metadata->retinas[$record->size] = $data;
832
+ break;
833
+ case self::IMAGE_TYPE_ORIGINAL:
834
+ $metadata->original_file = $data;
835
+ break;
836
+ }
837
 
838
+ }
839
+ } // extra info if
840
+ } // loop
841
 
842
  return $metadata;
843
  }
1182
  return $bool;
1183
  }
1184
 
1185
+ // The exclude size on the main image - via regex - if fails, prevents the whole thing from optimization.
1186
+ if ($this->processable_status == ImageModel::P_EXCLUDE_SIZE)
1187
+ {
1188
+ return $bool;
1189
+ }
1190
+
1191
  if (! $bool) // if parent is not processable, check if thumbnails are, can still have a work to do.
1192
  {
1193
 
1397
  //$meta = $meta? $meta : wp_get_attachment_metadata($ID);
1398
  $width = $this->get('width');
1399
  $height = $this->get('height');
1400
+
1401
+ // echo 'w/h'; print_r($width); echo ' '; print_r($height);
1402
+ Log::addTemp('Excluded w/h check ' . $width . ' ' . $height);
1403
+ // Log::addTemp('Check via', debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3));
1404
+
1405
  if( $width && $height
1406
  && $this->isProcessableSize($width, $height, $item["value"]) === false){
1407
  $this->processable_status = self::P_EXCLUDE_SIZE;
1589
  // ** Warning - This will also reset metadata
1590
  $bool = parent::restore();
1591
 
1592
+
1593
  if ($is_resized)
1594
  {
1595
  $wpmeta['width'] = $this->get('width');
1622
  $filebase = $thumbObj->getFileBase();
1623
  $is_resized = $thumbObj->getMeta('resize');
1624
  $size = $thumbObj->get('size');
1625
+ $unlisted_file = $thumbObj->getMeta('file');
1626
 
1627
+ // **** AFTER THIS IMAGE DATA IS WIPED! **** /
1628
  if (isset($restored[$filebase]))
1629
  {
1630
  $bool = true; // this filebase already restored. In case of duplicate sizes.
1635
  $bool = $thumbObj->restore(); // resets metadata
1636
  }
1637
 
1638
+ if ($unlisted_file === null)
1639
  {
 
 
 
1640
 
1641
+ if ($is_resized)
1642
+ {
1643
+ $wpmeta['sizes'][$size]['width'] = $thumbObj->get('width');
1644
+ $wpmeta['sizes'][$size]['height'] = $thumbObj->get('height');
1645
+ }
1646
+
1647
+ $wpmeta['sizes'][$size]['filesize'] = $thumbObj->getFileSize();
1648
+ }
1649
 
1650
  if (! $bool)
1651
  {
1909
  return false;
1910
  }
1911
 
 
1912
  $data = $metadata['ShortPixel'];
1913
 
1914
  if (count($data) == 0) // This can happen. Empty array is still nothing to convert.
1915
  return false;
1916
 
1917
  // Waiting for processing is a state where it's not optimized, or should be.
1918
+ // The last check is because it seems that it can be both improved and waiting something ( sigh ) // 04/07/22
1919
+ if (count($data) == 1 && isset($data['WaitingProcessing']) && ! isset($data['ShortPixelImprovement']))
1920
  {
1921
  return false;
1922
  }
1925
  $was_converted = get_post_meta($this->id, '_shortpixel_was_converted', true);
1926
  if ($was_converted == true || is_numeric($was_converted))
1927
  {
1928
+ $updateTs = 1656892800; // July 4th 2022 - 00:00 GMT
1929
+ if ($was_converted < $updateTs && $this->hasBackup())
1930
+ {
1931
+ $this->resetPrevent(); // reset any prevented optimized. This would have prob. thrown a backup issue.
1932
+ if ($this->isProcessable())
1933
+ {
1934
+ $this->deleteMeta();
1935
+ Log::addDebug('Conversion pre-bug detected with backup and still processable. Trying to fix by redoing legacy.');
1936
+ }
1937
+
1938
+ }
1939
+ else {
1940
+ Log::addDebug('No SPIO5 metadata, but this item was converted, not converting again');
1941
+ return false;
1942
+ }
1943
  }
1944
 
1945
  $quotaController = QuotaController::getInstance();
1950
  }
1951
 
1952
  Log::addDebug("Conversion of legacy: ", array($metadata));
1953
+
1954
  $type = isset($data['type']) ? $this->legacyConvertType($data['type']) : '';
1955
 
1956
  $improvement = (isset($metadata['ShortPixelImprovement']) && is_numeric($metadata['ShortPixelImprovement']) && $metadata['ShortPixelImprovement'] > 0) ? $metadata['ShortPixelImprovement'] : 0;
2150
  {
2151
  return $fileType->getFileName();
2152
  }
2153
+
2154
  $env = \wpSPIO()->env();
2155
  $fs = \wpSPIO()->filesystem();
2156
 
2157
  // try the whole thing, but fetching remote URLS, test if really S3 not in case something went wrong with is_virtual, or it's just something messed up.
2158
  if ($fileObj->is_virtual() && $env->plugin_active('s3-offload') )
2159
  {
2160
+
2161
+
2162
  if ($type == 'webp')
2163
  {
2164
  $is_double = \wpSPIO()->env()->useDoubleWebpExtension();
2196
  }
2197
  else
2198
  {
2199
+ $url_exists = $fs->url_exists($double_url);
2200
  if ($url_exists === true)
2201
  return $double_filename;
2202
  }
2396
  $added = false;
2397
  foreach($unlisted as $unName)
2398
  {
2399
+ if (isset($this->thumbnails[$unName]))
2400
+ {
2401
+ continue; // don't re-add if not needed.
2402
+ }
2403
  $thumbObj = $this->getThumbnailModel($path . $unName, $unName);
2404
  if ($thumbObj->getExtension() == 'webp' || $thumbObj->getExtension() == 'avif') // ignore webp/avif files.
2405
  {
2420
  }
2421
  }
2422
 
2423
+ //if ($added)
2424
+ // $this->saveMeta(); // Save it when we are adding images.
2425
 
2426
  self::$unlistedChecked[] = $this->get('id');
2427
  }
class/Model/Image/MediaLibraryThumbnailModel.php CHANGED
@@ -127,15 +127,24 @@ class MediaLibraryThumbnailModel extends \ShortPixel\Model\Image\ImageModel
127
  return array($this->getFullPath());
128
  }
129
 
130
- public function getOptimizeUrls()
 
131
  {
132
  if (! $this->isProcessable() )
133
  return array();
134
 
135
- $url = $this->getURL();
 
 
 
 
 
 
 
136
  if (! $url)
 
137
  return array(); //nothing
138
-
139
 
140
  return array($url);
141
  }
@@ -145,11 +154,16 @@ class MediaLibraryThumbnailModel extends \ShortPixel\Model\Image\ImageModel
145
  $fs = \wpSPIO()->filesystem();
146
 
147
  if ($this->size == 'original')
 
148
  $url = wp_get_original_image_url($this->id);
 
149
  elseif ($this->isUnlisted())
150
  $url = $fs->pathToUrl($this);
151
  else
152
- $url = wp_get_attachment_image_url($this->id, $this->size);
 
 
 
153
 
154
  return $this->fs()->checkURL($url);
155
  }
127
  return array($this->getFullPath());
128
  }
129
 
130
+ // get_path param see MediaLibraryModel
131
+ public function getOptimizeUrls($get_path = false)
132
  {
133
  if (! $this->isProcessable() )
134
  return array();
135
 
136
+ if (true === $get_path)
137
+ {
138
+ $url = $this->getFullPath();
139
+ }
140
+ else {
141
+ $url = $this->getURL();
142
+ }
143
+
144
  if (! $url)
145
+ {
146
  return array(); //nothing
147
+ }
148
 
149
  return array($url);
150
  }
154
  $fs = \wpSPIO()->filesystem();
155
 
156
  if ($this->size == 'original')
157
+ {
158
  $url = wp_get_original_image_url($this->id);
159
+ }
160
  elseif ($this->isUnlisted())
161
  $url = $fs->pathToUrl($this);
162
  else
163
+ {
164
+ $url = wp_get_attachment_image_url($this->id, $this->size);
165
+ }
166
+
167
 
168
  return $this->fs()->checkURL($url);
169
  }
class/ViewController.php CHANGED
@@ -45,15 +45,17 @@ class ViewController extends Controller
45
  */
46
  protected function checkPost()
47
  {
48
- if (count($_POST) == 0) // no post, nothing to check, return silent.
49
- return true;
50
 
51
- if (! isset($_POST['sp-nonce']) || ! wp_verify_nonce( $_POST['sp-nonce'], $this->form_action))
52
  {
53
  Log::addInfo('Check Post fails nonce check, action : ' . $this->form_action, array($_POST) );
54
  return false;
55
  }
56
- else if (isset($_POST) && count($_POST) > 0)
 
 
 
 
57
  {
58
  check_admin_referer( $this->form_action, 'sp-nonce' ); // extra check, when we are wrong here, it dies.
59
  unset($_POST['sp-nonce']);
45
  */
46
  protected function checkPost()
47
  {
 
 
48
 
49
+ if (! isset($_POST['sp-nonce']) || ! wp_verify_nonce( sanitize_key($_POST['sp-nonce']), $this->form_action))
50
  {
51
  Log::addInfo('Check Post fails nonce check, action : ' . $this->form_action, array($_POST) );
52
  return false;
53
  }
54
+ elseif(count($_POST) == 0) // no post, nothing to check, return silent.
55
+ {
56
+ return true;
57
+ }
58
+ elseif (isset($_POST) && count($_POST) > 0)
59
  {
60
  check_admin_referer( $this->form_action, 'sp-nonce' ); // extra check, when we are wrong here, it dies.
61
  unset($_POST['sp-nonce']);
class/external/cloudflare.php CHANGED
@@ -3,7 +3,7 @@ namespace ShortPixel;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
  use ShortPixel\Notices\NoticeController as Notices;
5
 
6
-
7
  class CloudFlareAPI {
8
  private $email; // $_cloudflareEmail
9
  private $authkey; // $_cloudflareAuthKey
@@ -80,7 +80,6 @@ class CloudFlareAPI {
80
  */
81
  private function start_cloudflare_cache_purge_process( $imageItem ) {
82
 
83
- //@TODO Also add the WebP and/or AVIF URLs to the purge list, for both Media Library and Custom Media items
84
 
85
  // Fetch CloudFlare API credentials
86
  /*$cloudflare_auth_email = $this->_cloudflareEmail;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
  use ShortPixel\Notices\NoticeController as Notices;
5
 
6
+ // @todo Clean up unused lines in this file. (cloudflare)
7
  class CloudFlareAPI {
8
  private $email; // $_cloudflareEmail
9
  private $authkey; // $_cloudflareAuthKey
80
  */
81
  private function start_cloudflare_cache_purge_process( $imageItem ) {
82
 
 
83
 
84
  // Fetch CloudFlare API credentials
85
  /*$cloudflare_auth_email = $this->_cloudflareEmail;
class/external/gravityforms.php CHANGED
@@ -7,7 +7,8 @@ class gravityForms
7
 
8
  public function __construct()
9
  {
10
- add_filter( 'gform_save_field_value', array($this,'shortPixelGravityForms'), 10, 5 );
 
11
  }
12
 
13
  function shortPixelGravityForms( $value, $lead, $field, $form ) {
7
 
8
  public function __construct()
9
  {
10
+ // @todo All this off, because it can only fatal error.
11
+ // add_filter( 'gform_save_field_value', array($this,'shortPixelGravityForms'), 10, 5 );
12
  }
13
 
14
  function shortPixelGravityForms( $value, $lead, $field, $form ) {
class/external/nextgen/nextGenController.php CHANGED
@@ -86,9 +86,17 @@ class NextGenController
86
  public function isNextGenScreen()
87
  {
88
  $screens = $this->add_screen_loads(array());
89
-
 
 
 
 
 
 
 
90
  $screen = get_current_screen();
91
 
 
92
  if (in_array($screen->id, $screens))
93
  return true;
94
  else
@@ -108,10 +116,9 @@ class NextGenController
108
  {
109
 
110
  $use_screens[] = 'toplevel_page_nextgen-gallery'; // toplevel
111
- $use_screens[] = 'gallery_page_ngg_addgallery'; // add gallery
112
- $use_screens[] = 'nggallery-manage-gallery'; // manage gallery - might be old
113
  $use_screens[] = 'nextgen-gallery_page_nggallery-manage-gallery'; // manage toplevel gallery
114
- $use_screens[] = 'gallery_page_nggallery-manage-album'; // manage album
115
  $use_screens[] = 'nggallery-manage-images'; // images in gallery overview
116
 
117
  return $use_screens;
86
  public function isNextGenScreen()
87
  {
88
  $screens = $this->add_screen_loads(array());
89
+ if (! is_admin())
90
+ {
91
+ return false;
92
+ }
93
+ if (! function_exists('get_current_screen'))
94
+ {
95
+ return false;
96
+ }
97
  $screen = get_current_screen();
98
 
99
+
100
  if (in_array($screen->id, $screens))
101
  return true;
102
  else
116
  {
117
 
118
  $use_screens[] = 'toplevel_page_nextgen-gallery'; // toplevel
119
+ $use_screens[] = 'nextgen-gallery_page_ngg_addgallery'; // add gallery
120
+ $use_screens[] = 'nextgen-gallery_page_nggallery-manage-album'; // manage album
121
  $use_screens[] = 'nextgen-gallery_page_nggallery-manage-gallery'; // manage toplevel gallery
 
122
  $use_screens[] = 'nggallery-manage-images'; // images in gallery overview
123
 
124
  return $use_screens;
class/external/spai.php CHANGED
@@ -14,10 +14,12 @@ class Spai
14
  {
15
  if (\wpSPIO()->env()->plugin_active('spai'))
16
  {
17
- // Prevent SPAI doing its stuff to our JSON returns.
18
  $hook_upon = array('shortpixel_image_processing', 'shortpixel_ajaxRequest');
19
  if (wp_doing_ajax() &&
 
20
  isset($_REQUEST['action']) &&
 
21
  in_array($_REQUEST['action'], $hook_upon) )
22
  {
23
  $this->preventCache();
14
  {
15
  if (\wpSPIO()->env()->plugin_active('spai'))
16
  {
17
+ // Prevent SPAI doing its stuff to our JSON returns.
18
  $hook_upon = array('shortpixel_image_processing', 'shortpixel_ajaxRequest');
19
  if (wp_doing_ajax() &&
20
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is not a form
21
  isset($_REQUEST['action']) &&
22
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is not a form
23
  in_array($_REQUEST['action'], $hook_upon) )
24
  {
25
  $this->preventCache();
class/external/wp-cli/wp-cli-base.php CHANGED
@@ -371,7 +371,7 @@ class SpioCommandBase
371
  \WP_CLI::error($result->message, false);
372
  }
373
  else {
374
- \WP_CLI::line($result->message);
375
  }
376
  }
377
 
@@ -463,6 +463,34 @@ class SpioCommandBase
463
  \WP_CLI\Utils\format_items('table', $items, $fields);
464
  }
465
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
466
  // Colored is buggy, so off for now -> https://github.com/wp-cli/php-cli-tools/issues/134
467
  private function textBoolean($bool, $colored = false)
468
  {
371
  \WP_CLI::error($result->message, false);
372
  }
373
  else {
374
+ \WP_CLI::line($result->message);
375
  }
376
  }
377
 
463
  \WP_CLI\Utils\format_items('table', $items, $fields);
464
  }
465
 
466
+ /**
467
+ * Clears the Queue(s)
468
+ *
469
+ *
470
+ * [--queue=<name>]
471
+ * : Either 'media' or 'custom' . Omit to run both.
472
+ * ---
473
+ * default: media,custom
474
+ * options:
475
+ * - media
476
+ * - custom
477
+ *
478
+ */
479
+ public function clear($args, $assoc)
480
+ {
481
+ $queues = $this->getQueueArgument($assoc);
482
+ $optimizeController = $this->getOptimizeController();
483
+
484
+ foreach($queues as $type)
485
+ {
486
+ $queue = $optimizeController->getQueue($type);
487
+ $queue->resetQueue();
488
+ }
489
+
490
+ \WP_CLI::Success(__('Queue(s) cleared', 'shortpixel-image-optimiser'));
491
+
492
+ }
493
+
494
  // Colored is buggy, so off for now -> https://github.com/wp-cli/php-cli-tools/issues/134
495
  private function textBoolean($bool, $colored = false)
496
  {
class/external/wp-offload-media.php CHANGED
@@ -21,6 +21,8 @@ class wpOffload
21
  protected $is_cname = false;
22
  protected $cname;
23
 
 
 
24
  // if might have to do these checks many times for each thumbnails, keep it fastish.
25
  //protected $retrievedCache = array();
26
 
@@ -95,8 +97,6 @@ class wpOffload
95
 
96
  }
97
 
98
-
99
-
100
  public function returnOriginalFile($file, $attach_id)
101
  {
102
  $file = get_attached_file($attach_id, true);
@@ -183,32 +183,106 @@ class wpOffload
183
  return $mediaItem;
184
  }
185
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
 
187
  public function checkIfOffloaded($bool, $url)
188
  {
189
- $source_id = $this->getSourceIDByURL($url);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
 
191
  if ($source_id !== false)
 
192
  return true;
 
193
  else
194
  return false;
195
  }
196
 
197
  protected function getSourceIDByURL($url)
198
  {
199
- $class = $this->getMediaClass();
200
- $source = $class::get_item_source_by_remote_url($url);
201
 
202
- $source_id = isset($source['id']) ? intval($source['id']) : false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
203
 
204
- if ($source_id !== false)
205
- return $source_id;
206
- else
207
- {
208
- $source_id = $this->checkIfThumbnail($url); // can be item or false.
209
- return $source_id;
210
  }
211
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
  return false;
213
  }
214
 
@@ -216,16 +290,12 @@ class wpOffload
216
  private function checkIfThumbnail($original_url)
217
  {
218
  //$result = \attachment_url_to_postid($url);
219
- $pattern = '/(.*)-\d+[xX]\d+(\.\w+)/m';
220
- $url = preg_replace($pattern, '$1$2', $original_url);
221
-
222
- $class = $this->getMediaClass();
223
- $source = $class::get_item_source_by_remote_url($url);
224
-
225
- $source_id = isset($source['id']) ? intval($source['id']) : false;
226
 
227
  if ($source_id !== false)
 
 
228
  return $source_id;
 
229
  else
230
  return false;
231
 
21
  protected $is_cname = false;
22
  protected $cname;
23
 
24
+ private $sources; // cache for url > source_id lookup, to prevent duplicate queries.
25
+
26
  // if might have to do these checks many times for each thumbnails, keep it fastish.
27
  //protected $retrievedCache = array();
28
 
97
 
98
  }
99
 
 
 
100
  public function returnOriginalFile($file, $attach_id)
101
  {
102
  $file = get_attached_file($attach_id, true);
183
  return $mediaItem;
184
  }
185
 
186
+ private function sourceCache($url, $source_id = null)
187
+ {
188
+ if ($source_id === null && isset($this->sources[$url]))
189
+ {
190
+ $source_id = $this->sources[$url];
191
+ return $source_id;
192
+ }
193
+ elseif ($source_id !== null)
194
+ {
195
+ if (! isset($this->sources[$url]))
196
+ {
197
+ $this->sources[$url] = $source_id;
198
+ }
199
+ return $source_id;
200
+ }
201
+
202
+ return false;
203
+ }
204
 
205
  public function checkIfOffloaded($bool, $url)
206
  {
207
+
208
+ $source_id = $this->sourceCache($url);
209
+
210
+
211
+ if (false === $source_id)
212
+ {
213
+ $extension = substr($url, strrpos($url, '.') + 1);
214
+ // If these filetypes are not in the cache, they cannot be found via geSourceyIDByUrl method ( not in path DB ), so it's pointless to try. If they are offloaded, at some point the extra-info might load.
215
+ if ($extension == 'webp' || $extension == 'avif')
216
+ {
217
+ return false;
218
+ }
219
+
220
+ $source_id = $this->getSourceIDByURL($url);
221
+ }
222
 
223
  if ($source_id !== false)
224
+ {
225
  return true;
226
+ }
227
  else
228
  return false;
229
  }
230
 
231
  protected function getSourceIDByURL($url)
232
  {
 
 
233
 
234
+ $source_id = $this->sourceCache($url); // check cache first.
235
+
236
+ if (false === $source_id) // check on the raw url.
237
+ {
238
+ $class = $this->getMediaClass();
239
+ $source = $class::get_item_source_by_remote_url($url);
240
+ $source_id = isset($source['id']) ? intval($source['id']) : false;
241
+ }
242
+
243
+ if (false === $source_id) // check now via the thumbnail hocus.
244
+ {
245
+ $pattern = '/(.*)-\d+[xX]\d+(\.\w+)/m';
246
+ $url = preg_replace($pattern, '$1$2', $url);
247
+
248
+ $source_id = $this->sourceCache($url); // check cache first.
249
+
250
+ if (false === $source_id)
251
+ {
252
+ $source = $class::get_item_source_by_remote_url($url);
253
+ $source_id = isset($source['id']) ? intval($source['id']) : false;
254
+ }
255
 
 
 
 
 
 
 
256
  }
257
 
258
+ if ($source_id !== false)
259
+ {
260
+
261
+ $this->sourceCache($url, $source_id); // cache it.
262
+
263
+ // get item
264
+ $item = $this->getItemById($source_id);
265
+ if (is_object($item) && method_exists($item, 'extra_info'))
266
+ {
267
+ $baseUrl = str_replace(basename($url),'', $url);
268
+ $extra_info = $item->extra_info();
269
+
270
+ if (isset($extra_info['objects']))
271
+ {
272
+ foreach($extra_info['objects'] as $extraItem)
273
+ {
274
+ if (is_array($extraItem) && isset($extraItem['source_file']))
275
+ {
276
+ // Add source stuff into cache.
277
+ $this->sourceCache($baseUrl . $extraItem['source_file'], $source_id);
278
+ }
279
+ }
280
+ }
281
+ }
282
+
283
+ return $source_id;
284
+ }
285
+
286
  return false;
287
  }
288
 
290
  private function checkIfThumbnail($original_url)
291
  {
292
  //$result = \attachment_url_to_postid($url);
 
 
 
 
 
 
 
293
 
294
  if ($source_id !== false)
295
+ {
296
+ $this->sourceCache($url, $source_id);
297
  return $source_id;
298
+ }
299
  else
300
  return false;
301
 
class/view/bulk/part-bulk-special.php CHANGED
@@ -7,17 +7,17 @@ use \ShortPixel\Controller\BulkController as BulkController;
7
 
8
  <section class='panel bulk-restore' data-panel="bulk-restore" >
9
  <h3 class='heading'>
10
- <?php _e("Bulk Restore", 'shortpixel-image-optimiser'); ?>
11
  </h3>
12
 
13
 
14
  <div class='bulk-special-wrapper'>
15
 
16
- <h4 class='warning'><?php _e('Warning', 'shortpixel-image-optimiser'); ?></h4>
17
 
18
- <p><?php printf(__('By starting the %s bulk restore %s process, the plugin will try to restore %s all images %s to the original state. All images will become unoptimized.', 'shortpixel-image-optimiser'), '<b>', '</b>', '<b>', '</b>'); ?></p>
19
 
20
- <p class='warning'><?php _e('It is strongly advised to create a full backup before starting this process.', 'shortpixel-image-optimiser'); ?></p>
21
 
22
  <?php if ($this->view->approx->custom->has_custom === true) : ?>
23
  <div class='optiongroup' data-check-visibility data-control="data-check-custom-hascustom">
@@ -28,7 +28,7 @@ use \ShortPixel\Controller\BulkController as BulkController;
28
  <div class="the_switch">&nbsp; </div>
29
  </label>
30
  </div>
31
- <h4><label for="restore_media_checkbox"><?php _e('Restore media library','shortpixel-image-optimiser'); ?></label></h4>
32
  </div>
33
 
34
 
@@ -39,18 +39,18 @@ use \ShortPixel\Controller\BulkController as BulkController;
39
  <div class="the_switch">&nbsp; </div>
40
  </label>
41
  </div>
42
- <h4><label for="restore_custom_checkbox"><?php _e('Restore custom media','shortpixel-image-optimiser'); ?></label></h4>
43
  </div>
44
  <?php endif ?>
45
- <p class='optiongroup warning hidden' id="restore_media_warn"><?php _e('Please select one of the options', 'shortpixel-image-optimiser'); ?></p>
46
 
47
- <p class='optiongroup' ><input type="checkbox" id="bulk-restore-agree" value="agree" data-action="ToggleButton" data-target="bulk-restore-button"> <?php _e('I want to restore all selected images. I understand this action is permanent and nonreversible', 'shortpixel-image-optimiser'); ?></p>
48
 
49
 
50
  <nav>
51
- <button type="button" class="button" data-action="open-panel" data-panel="dashboard"><?php _e('Back','shortpixel-image-optimiser'); ?></button>
52
 
53
- <button type="button" class="button button-primary disabled" id='bulk-restore-button' data-action="BulkRestoreAll" disabled><?php _e('Bulk Restore All Images', 'shortpixel-image-optimiser') ?></button>
54
 
55
  </nav>
56
 
@@ -60,26 +60,26 @@ use \ShortPixel\Controller\BulkController as BulkController;
60
 
61
  <section class='panel bulk-migrate' data-panel="bulk-migrate" >
62
  <h3 class='heading'>
63
- <?php _e("Bulk Migrate", 'shortpixel-image-optimiser'); ?>
64
  </h3>
65
 
66
  <div class='bulk-special-wrapper'>
67
 
68
- <h4 class='warning'><?php _e('Warning', 'shortpixel-image-optimiser'); ?></h4>
69
 
70
- <p><?php printf(__('By starting the %s bulk metadata migration %s process, the plugin will try to migrate the old format of optimization information (used by the plugin for versions prior to 5.0) to the new format used from version 5.0 onward for %s all the images. %s It is possible to have exceptions and some of the image information migration may fail. You should get all the details for these cases at the end of the process, in the Errors section.', 'shortpixel-image-optimiser'), '<b>', '</b>', '<b>', '</b>'); ?></p>
71
 
72
- <p class='warning optiongroup'><?php _e('It is strongly advised to create a full backup before starting this process.', 'shortpixel-image-optimiser'); ?></p>
73
 
74
- <p class='optiongroup'><input type="checkbox" id="bulk-migrate-agree" value="agree" data-action="ToggleButton" data-target="bulk-migrate-button"> <?php _e('I want to migrate the metadata for all images. I understand this action is permanent. I made a backup of my site including images and database.', 'shortpixel-image-optimiser'); ?></p>
75
 
76
 
77
  <nav>
78
 
79
 
80
- <button class="button" type="button" data-action="open-panel" data-panel="dashboard"><?php _e('Back','shortpixel-image-optimiser'); ?></button>
81
 
82
- <button type="button" type="button" class="button disabled button-primary" disabled id='bulk-migrate-button' data-action="BulkMigrateAll" ><?php _e('Search and migrate All Images', 'shortpixel-image-optimiser') ?>
83
  </button>
84
 
85
  </nav>
@@ -88,24 +88,24 @@ use \ShortPixel\Controller\BulkController as BulkController;
88
 
89
  <section class='panel bulk-removeLegacy' data-panel="bulk-removeLegacy" >
90
  <h3 class='heading'>
91
- <?php _e("Bulk remove legacy data", 'shortpixel-image-optimiser'); ?>
92
  </h3>
93
 
94
  <div class='bulk-special-wrapper'>
95
 
96
- <h4 class='warning'><?php _e('Warning', 'shortpixel-image-optimiser'); ?></h4>
97
 
98
- <p><?php printf(__('By starting the %s remove legacy metadata %s process, the plugin will try to remove all the %s legacy data %s (that was used by the plugin to store the optimization information in versions earlier than 5.0). If this legacy metadata isn\'t properly migrated or some of the migration failed for any reason, it will be impossible to undo or redo the process. In these cases, the optimization information for images processed with versions earlier than 5.0 could be lost.', 'shortpixel-image-optimiser'), '<b>', '</b>', '<b>', '</b>'); ?></p>
99
 
100
- <p class='warning optiongroup'><?php _e('It is strongly advised to create a full backup before starting this process.', 'shortpixel-image-optimiser'); ?></p>
101
- <p class='optiongroup'><input type="checkbox" id="bulk-migrate-agree" value="agree" data-action="ToggleButton" data-target="bulk-removelegacy-button"> <?php _e('I want to remove all legacy data. I understand this action is permanent. I made a backup of my site including images and database.', 'shortpixel-image-optimiser'); ?></p>
102
 
103
 
104
  <nav>
105
 
106
- <button type="button" class="button" data-action="open-panel" data-panel="dashboard"><?php _e('Back','shortpixel-image-optimiser'); ?></button>
107
 
108
- <button type="button" class="button disabled button-primary" disabled id='bulk-removelegacy-button' data-action="BulkRemoveLegacy" ><?php _e('Remove all legacy metadata', 'shortpixel-image-optimiser') ?></button>
109
 
110
  </nav>
111
  </div>
7
 
8
  <section class='panel bulk-restore' data-panel="bulk-restore" >
9
  <h3 class='heading'>
10
+ <?php esc_html_e("Bulk Restore", 'shortpixel-image-optimiser'); ?>
11
  </h3>
12
 
13
 
14
  <div class='bulk-special-wrapper'>
15
 
16
+ <h4 class='warning'><?php esc_html_e('Warning', 'shortpixel-image-optimiser'); ?></h4>
17
 
18
+ <p><?php printf(esc_html__('By starting the %s bulk restore %s process, the plugin will try to restore %s all images %s to the original state. All images will become unoptimized.', 'shortpixel-image-optimiser'), '<b>', '</b>', '<b>', '</b>'); ?></p>
19
 
20
+ <p class='warning'><?php esc_html_e('It is strongly advised to create a full backup before starting this process.', 'shortpixel-image-optimiser'); ?></p>
21
 
22
  <?php if ($this->view->approx->custom->has_custom === true) : ?>
23
  <div class='optiongroup' data-check-visibility data-control="data-check-custom-hascustom">
28
  <div class="the_switch">&nbsp; </div>
29
  </label>
30
  </div>
31
+ <h4><label for="restore_media_checkbox"><?php esc_html_e('Restore media library','shortpixel-image-optimiser'); ?></label></h4>
32
  </div>
33
 
34
 
39
  <div class="the_switch">&nbsp; </div>
40
  </label>
41
  </div>
42
+ <h4><label for="restore_custom_checkbox"><?php esc_html_e('Restore custom media','shortpixel-image-optimiser'); ?></label></h4>
43
  </div>
44
  <?php endif ?>
45
+ <p class='optiongroup warning hidden' id="restore_media_warn"><?php esc_html_e('Please select one of the options', 'shortpixel-image-optimiser'); ?></p>
46
 
47
+ <p class='optiongroup' ><input type="checkbox" id="bulk-restore-agree" value="agree" data-action="ToggleButton" data-target="bulk-restore-button"> <?php esc_html_e('I want to restore all selected images. I understand this action is permanent and nonreversible', 'shortpixel-image-optimiser'); ?></p>
48
 
49
 
50
  <nav>
51
+ <button type="button" class="button" data-action="open-panel" data-panel="dashboard"><?php esc_html_e('Back','shortpixel-image-optimiser'); ?></button>
52
 
53
+ <button type="button" class="button button-primary disabled" id='bulk-restore-button' data-action="BulkRestoreAll" disabled><?php esc_html_e('Bulk Restore All Images', 'shortpixel-image-optimiser') ?></button>
54
 
55
  </nav>
56
 
60
 
61
  <section class='panel bulk-migrate' data-panel="bulk-migrate" >
62
  <h3 class='heading'>
63
+ <?php esc_html_e("Bulk Migrate", 'shortpixel-image-optimiser'); ?>
64
  </h3>
65
 
66
  <div class='bulk-special-wrapper'>
67
 
68
+ <h4 class='warning'><?php esc_html_e('Warning', 'shortpixel-image-optimiser'); ?></h4>
69
 
70
+ <p><?php printf(esc_html__('By starting the %s bulk metadata migration %s process, the plugin will try to migrate the old format of optimization information (used by the plugin for versions prior to 5.0) to the new format used from version 5.0 onward for %s all the images. %s It is possible to have exceptions and some of the image information migration may fail. You should get all the details for these cases at the end of the process, in the Errors section.', 'shortpixel-image-optimiser'), '<b>', '</b>', '<b>', '</b>'); ?></p>
71
 
72
+ <p class='warning optiongroup'><?php esc_html_e('It is strongly advised to create a full backup before starting this process.', 'shortpixel-image-optimiser'); ?></p>
73
 
74
+ <p class='optiongroup'><input type="checkbox" id="bulk-migrate-agree" value="agree" data-action="ToggleButton" data-target="bulk-migrate-button"> <?php esc_html_e('I want to migrate the metadata for all images. I understand this action is permanent. I made a backup of my site including images and database.', 'shortpixel-image-optimiser'); ?></p>
75
 
76
 
77
  <nav>
78
 
79
 
80
+ <button class="button" type="button" data-action="open-panel" data-panel="dashboard"><?php esc_html_e('Back','shortpixel-image-optimiser'); ?></button>
81
 
82
+ <button type="button" type="button" class="button disabled button-primary" disabled id='bulk-migrate-button' data-action="BulkMigrateAll" ><?php esc_html_e('Search and migrate All Images', 'shortpixel-image-optimiser') ?>
83
  </button>
84
 
85
  </nav>
88
 
89
  <section class='panel bulk-removeLegacy' data-panel="bulk-removeLegacy" >
90
  <h3 class='heading'>
91
+ <?php esc_html_e("Bulk remove legacy data", 'shortpixel-image-optimiser'); ?>
92
  </h3>
93
 
94
  <div class='bulk-special-wrapper'>
95
 
96
+ <h4 class='warning'><?php esc_html_e('Warning', 'shortpixel-image-optimiser'); ?></h4>
97
 
98
+ <p><?php printf(esc_html__('By starting the %s remove legacy metadata %s process, the plugin will try to remove all the %s legacy data %s (that was used by the plugin to store the optimization information in versions earlier than 5.0). If this legacy metadata isn\'t properly migrated or some of the migration failed for any reason, it will be impossible to undo or redo the process. In these cases, the optimization information for images processed with versions earlier than 5.0 could be lost.', 'shortpixel-image-optimiser'), '<b>', '</b>', '<b>', '</b>'); ?></p>
99
 
100
+ <p class='warning optiongroup'><?php esc_html_e('It is strongly advised to create a full backup before starting this process.', 'shortpixel-image-optimiser'); ?></p>
101
+ <p class='optiongroup'><input type="checkbox" id="bulk-migrate-agree" value="agree" data-action="ToggleButton" data-target="bulk-removelegacy-button"> <?php esc_html_e('I want to remove all legacy data. I understand this action is permanent. I made a backup of my site including images and database.', 'shortpixel-image-optimiser'); ?></p>
102
 
103
 
104
  <nav>
105
 
106
+ <button type="button" class="button" data-action="open-panel" data-panel="dashboard"><?php esc_html_e('Back','shortpixel-image-optimiser'); ?></button>
107
 
108
+ <button type="button" class="button disabled button-primary" disabled id='bulk-removelegacy-button' data-action="BulkRemoveLegacy" ><?php esc_html_e('Remove all legacy metadata', 'shortpixel-image-optimiser') ?></button>
109
 
110
  </nav>
111
  </div>
class/view/bulk/part-dashboard.php CHANGED
@@ -3,14 +3,11 @@ namespace ShortPixel;
3
  ?>
4
 
5
  <section class='dashboard panel active' data-panel="dashboard" style='display: block' >
6
-
7
- <?php //$this->loadView('bulk/part-progressbar', false); ?>
8
-
9
  <div class="panel-container">
10
 
11
 
12
- <h3 class="heading"><span><img src="<?php echo \wpSPIO()->plugin_url('res/img/robo-slider.png'); ?>"></span>
13
- <?php _e('Welcome to the Bulk Processing page!', 'shortpixel-image-optimiser'); ?>
14
  </h3>
15
 
16
  <div class='interface wrapper'>
@@ -18,36 +15,26 @@ namespace ShortPixel;
18
  <div class='bulk-wrapper'>
19
  <button type="button" class="button-primary button" id="start-optimize" data-action="open-panel" data-panel="selection" <?php echo ($this->view->error) ? "disabled" : ''; ?> >
20
  <span class='dashicons dashicons-controls-play'>&nbsp;</span>
21
- <p><?php _e('Start optimizing','shortpixel-image-optimiser'); ?></p>
22
  </button>
23
  </div>
24
 
25
- <p class='description'><?php _e('Here you can (re)optimize your Media Library or Custom Media folders from your website.', 'shortpixel-image-optimiser'); ?></p>
26
 
27
  </div>
28
 
29
  <?php if ($this->view->error): ?>
30
  <div class='bulk error'>
31
- <h3><?php echo $this->view->errorTitle; ?></h3>
32
- <p><?php echo $this->view->errorContent; ?></p>
33
  <?php if (property_exists($this->view, 'errorText')): ?>
34
- <p class='text'><?php echo $this->view->errorText ?></p>
35
  <?php endif; ?>
36
 
37
  </div>
38
 
39
  <?php endif; ?>
40
 
41
- <?php if (! $this->view->error): /*
42
- <div class='advanced-actions'>
43
- <h4><?php _e('Advanced Options','shortpixel-image-optimiser'); ?></h4>
44
- <button type="button" class="button" id="bulk-restore" data-action='open-panel' data-panel="bulk-restore"><?php _e('Bulk Restore', 'shortpixel-image-optimiser'); ?></button>
45
- <button type="button" class="button" id="bulk-restore" data-action='open-panel' data-panel="bulk-migrate"><?php _e('Migrate from 4x', 'shortpixel-image-optimiser'); ?></button>
46
-
47
- </div>
48
-
49
- */ endif; ?>
50
-
51
  <?php if (count($this->view->logs) > 0): ?>
52
 
53
  <div id="LogModal" class="shortpixel-modal shortpixel-hide bulk-modal">
@@ -65,24 +52,24 @@ namespace ShortPixel;
65
  <div id="LogModal-Shade" class='sp-modal-shade'></div>
66
  <div class='dashboard-log'>
67
 
68
- <h3><?php _e('Previous Bulks', 'shortpixel_image_optimizer'); ?></h3>
69
  <?php
70
  echo "<div class='head'>";
71
  foreach($this->view->logHeaders as $header)
72
  {
73
- echo "<span>$header</span>";
74
  }
75
  echo "</div>";
76
  foreach ($this->view->logs as $logItem):
77
  {
78
- echo "<div class='data " . $logItem['type'] . "'>";
79
 
80
- echo "<span>" . $logItem['images'] . '</span>';
81
  echo "<span>" . $logItem['errors'] . '</span>';
82
 
83
- echo '<span class="checkmark_green date">' . sprintf(__('%sCompleted%s on %s','shortpixel-image-optimiser'), '<b>','</b>', $logItem['date']) . '</span>';
84
 
85
- echo "<span>" . $logItem['bulkName'] . '</span>';
86
 
87
  echo "</div>";
88
  }
@@ -101,7 +88,7 @@ namespace ShortPixel;
101
  <span class="svg-spinner"><?php $this->loadView('snippets/part-svgloader', false); ?></span>
102
 
103
  <span>
104
- <h2>Please wait, ShortPixel is loading</h2>
105
 
106
  </span>
107
 
3
  ?>
4
 
5
  <section class='dashboard panel active' data-panel="dashboard" style='display: block' >
 
 
 
6
  <div class="panel-container">
7
 
8
 
9
+ <h3 class="heading"><span><img src="<?php echo esc_url(\wpSPIO()->plugin_url('res/img/robo-slider.png')); ?>"></span>
10
+ <?php esc_html_e('Welcome to the Bulk Processing page!', 'shortpixel-image-optimiser'); ?>
11
  </h3>
12
 
13
  <div class='interface wrapper'>
15
  <div class='bulk-wrapper'>
16
  <button type="button" class="button-primary button" id="start-optimize" data-action="open-panel" data-panel="selection" <?php echo ($this->view->error) ? "disabled" : ''; ?> >
17
  <span class='dashicons dashicons-controls-play'>&nbsp;</span>
18
+ <p><?php esc_html_e('Start optimizing','shortpixel-image-optimiser'); ?></p>
19
  </button>
20
  </div>
21
 
22
+ <p class='description'><?php esc_html_e('Here you can (re)optimize your Media Library or Custom Media folders from your website.', 'shortpixel-image-optimiser'); ?></p>
23
 
24
  </div>
25
 
26
  <?php if ($this->view->error): ?>
27
  <div class='bulk error'>
28
+ <h3><?php echo esc_html($this->view->errorTitle); ?></h3>
29
+ <p><?php echo esc_html($this->view->errorContent); ?></p>
30
  <?php if (property_exists($this->view, 'errorText')): ?>
31
+ <p class='text'><?php echo esc_html($this->view->errorText) ?></p>
32
  <?php endif; ?>
33
 
34
  </div>
35
 
36
  <?php endif; ?>
37
 
 
 
 
 
 
 
 
 
 
 
38
  <?php if (count($this->view->logs) > 0): ?>
39
 
40
  <div id="LogModal" class="shortpixel-modal shortpixel-hide bulk-modal">
52
  <div id="LogModal-Shade" class='sp-modal-shade'></div>
53
  <div class='dashboard-log'>
54
 
55
+ <h3><?php esc_html_e('Previous Bulks', 'shortpixel_image_optimizer'); ?></h3>
56
  <?php
57
  echo "<div class='head'>";
58
  foreach($this->view->logHeaders as $header)
59
  {
60
+ echo "<span>" . esc_attr($header) . "</span>";
61
  }
62
  echo "</div>";
63
  foreach ($this->view->logs as $logItem):
64
  {
65
+ echo "<div class='data " . esc_attr($logItem['type']) . "'>";
66
 
67
+ echo "<span>" . esc_html($logItem['images']) . '</span>';
68
  echo "<span>" . $logItem['errors'] . '</span>';
69
 
70
+ echo '<span class="checkmark_green date">' . sprintf(esc_html__('%sCompleted%s on %s','shortpixel-image-optimiser'), '<b>','</b>', esc_html($logItem['date'])) . '</span>';
71
 
72
+ echo "<span>" . esc_html($logItem['bulkName']) . '</span>';
73
 
74
  echo "</div>";
75
  }
88
  <span class="svg-spinner"><?php $this->loadView('snippets/part-svgloader', false); ?></span>
89
 
90
  <span>
91
+ <h2><?php esc_html_e('Please wait, ShortPixel is loading'); ?></h2>
92
 
93
  </span>
94
 
class/view/bulk/part-finished.php CHANGED
@@ -1,15 +1,13 @@
1
  <?php
2
-
3
  namespace ShortPixel;
4
-
5
  ?>
6
  <section class="panel finished" data-panel="finished">
7
  <div class="panel-container">
8
 
9
  <h3 class="heading"><span><img src="<?php echo \wpSPIO()->plugin_url('res/img/robo-slider.png'); ?>"></span>
10
- <?php _e('The ShortPixel Bulk Processing is finished' ,'shortpixel-image-optimiser'); ?>
11
  <div class='average-optimization'>
12
- <p><?php _e('Average this run','shortpixel-image-optimiser'); ?></p>
13
  <svg class="opt-circle-average" viewBox="-10 0 150 140">
14
  <path class="trail" d="
15
  M 50,50
@@ -25,7 +23,7 @@ namespace ShortPixel;
25
  a 46,46 0 1 1 0,-92
26
  " stroke-width="16" fill-opacity="0" style="stroke-dasharray: 289.027px, 289.027px; stroke-dashoffset: 180px;">
27
  </path>
28
- <text class="text" x="50" y="50"><?php _e('N/A', 'shortpixel-image-optimiser'); ?></text>
29
  </svg>
30
 
31
  </div>
@@ -36,24 +34,24 @@ namespace ShortPixel;
36
 
37
  <div class='bulk-summary' data-check-visibility data-control="data-check-media-total">
38
  <div class='heading'>
39
- <span><i class='dashicons dashicons-images-alt2'>&nbsp;</i> <?php _e('Media Library','shortpixel-image-optimiser'); ?></span>
40
  <span>
41
  <span class='line-progressbar'>
42
  <span class='done-text'><i data-stats-media="percentage_done"></i> %</span>
43
  <span class='done' data-stats-media="percentage_done" data-presentation="css.width.percentage"></span>
44
  </span>
45
  </span>
46
- <span><?php _e('Processing','shortpixel-image-optimiser') ?>: <i data-stats-media="in_process">-</i></span>
47
 
48
  </div>
49
 
50
  <div>
51
- <span><?php _e('Processed','shortpixel-image-optimiser'); ?>: <i data-stats-media="done">-</i></span>
52
 
53
- <span><?php _e('Images Left','shortpixel-image-optimiser'); ?>: <i data-stats-media="in_queue">-</i></span>
54
- <span><?php _e('Errors','shortpixel-image-optimiser'); ?>: <i data-check-media-fatalerrors data-stats-media="fatal_errors" class='error'>- </i>
55
- <span class="display-error-box" data-check-visibility data-control="data-check-media-fatalerrors" ><label title="<?php _e('Show Errors', 'shortpixel-image-optimiser'); ?>">
56
- <input type="checkbox" name="show-errors" value="show" data-action='ToggleErrorBox' data-errorbox='media' data-event='change'><?php _e('Show Errors','shortpixel-image-optimiser'); ?></label>
57
  </span>
58
  </span>
59
 
@@ -76,22 +74,22 @@ namespace ShortPixel;
76
 
77
  <div class='bulk-summary' data-check-visibility data-control="data-check-custom-total">
78
  <div class='heading'>
79
- <span><i class='dashicons dashicons-open-folder'>&nbsp;</i> <?php _e('Custom Media','shortpixel-image-optimiser'); ?></span>
80
  <span>
81
  <span class='line-progressbar'>
82
  <span class='done-text'><i data-stats-custom="percentage_done"></i> %</span>
83
  <span class='done' data-stats-custom="percentage_done" data-presentation="css.width.percentage"></span>
84
  </span>
85
  </span>
86
- <span><?php _e('Processing','shortpixel-image-optimiser') ?>: <i data-stats-custom="in_process">-</i></span>
87
 
88
  </div>
89
  <div>
90
- <span><?php _e('Processed','shortpixel-image-optimiser'); ?>: <i data-stats-custom="done">-</i></span>
91
 
92
- <span><?php _e('Images Left', 'shortpixel-image-optimiser') ?>: <i data-stats-custom="in_queue">-</i></span>
93
- <span><?php _e('Errors','shortpixel-image-optimiser') ?>: <i data-check-custom-fatalerrors data-stats-custom="fatal_errors" class='error'>-</i>
94
- <span class="display-error-box" data-check-visibility data-control="data-check-custom-fatalerrors" ><label title="<?php _e('Show Errors', 'shortpixel-image-optimiser'); ?>">
95
  <input type="checkbox" name="show-errors" value="show" data-action='ToggleErrorBox' data-errorbox='custom' data-event='change'>Show Errors</label>
96
  </span>
97
  </span>
@@ -110,7 +108,7 @@ namespace ShortPixel;
110
 
111
 
112
  <nav>
113
- <button class='button finish' type="button" data-action="FinishBulk" id="FinishBulkButton">Finish Bulk Process</button>
114
  </nav>
115
 
116
 
1
  <?php
 
2
  namespace ShortPixel;
 
3
  ?>
4
  <section class="panel finished" data-panel="finished">
5
  <div class="panel-container">
6
 
7
  <h3 class="heading"><span><img src="<?php echo \wpSPIO()->plugin_url('res/img/robo-slider.png'); ?>"></span>
8
+ <?php esc_html_e('The ShortPixel Bulk Processing is finished' ,'shortpixel-image-optimiser'); ?>
9
  <div class='average-optimization'>
10
+ <p><?php esc_html_e('Average this run','shortpixel-image-optimiser'); ?></p>
11
  <svg class="opt-circle-average" viewBox="-10 0 150 140">
12
  <path class="trail" d="
13
  M 50,50
23
  a 46,46 0 1 1 0,-92
24
  " stroke-width="16" fill-opacity="0" style="stroke-dasharray: 289.027px, 289.027px; stroke-dashoffset: 180px;">
25
  </path>
26
+ <text class="text" x="50" y="50"><?php esc_html_e('N/A', 'shortpixel-image-optimiser'); ?></text>
27
  </svg>
28
 
29
  </div>
34
 
35
  <div class='bulk-summary' data-check-visibility data-control="data-check-media-total">
36
  <div class='heading'>
37
+ <span><i class='dashicons dashicons-images-alt2'>&nbsp;</i> <?php esc_html_e('Media Library','shortpixel-image-optimiser'); ?></span>
38
  <span>
39
  <span class='line-progressbar'>
40
  <span class='done-text'><i data-stats-media="percentage_done"></i> %</span>
41
  <span class='done' data-stats-media="percentage_done" data-presentation="css.width.percentage"></span>
42
  </span>
43
  </span>
44
+ <span><?php esc_html_e('Processing','shortpixel-image-optimiser') ?>: <i data-stats-media="in_process">-</i></span>
45
 
46
  </div>
47
 
48
  <div>
49
+ <span><?php esc_html_e('Processed','shortpixel-image-optimiser'); ?>: <i data-stats-media="done">-</i></span>
50
 
51
+ <span><?php esc_html_e('Images Left','shortpixel-image-optimiser'); ?>: <i data-stats-media="in_queue">-</i></span>
52
+ <span><?php esc_html_e('Errors','shortpixel-image-optimiser'); ?>: <i data-check-media-fatalerrors data-stats-media="fatal_errors" class='error'>- </i>
53
+ <span class="display-error-box" data-check-visibility data-control="data-check-media-fatalerrors" ><label title="<?php esc_html_e('Show Errors', 'shortpixel-image-optimiser'); ?>">
54
+ <input type="checkbox" name="show-errors" value="show" data-action='ToggleErrorBox' data-errorbox='media' data-event='change'><?php esc_html_e('Show Errors','shortpixel-image-optimiser'); ?></label>
55
  </span>
56
  </span>
57
 
74
 
75
  <div class='bulk-summary' data-check-visibility data-control="data-check-custom-total">
76
  <div class='heading'>
77
+ <span><i class='dashicons dashicons-open-folder'>&nbsp;</i> <?php esc_html_e('Custom Media','shortpixel-image-optimiser'); ?></span>
78
  <span>
79
  <span class='line-progressbar'>
80
  <span class='done-text'><i data-stats-custom="percentage_done"></i> %</span>
81
  <span class='done' data-stats-custom="percentage_done" data-presentation="css.width.percentage"></span>
82
  </span>
83
  </span>
84
+ <span><?php esc_html_e('Processing','shortpixel-image-optimiser') ?>: <i data-stats-custom="in_process">-</i></span>
85
 
86
  </div>
87
  <div>
88
+ <span><?php esc_html_e('Processed','shortpixel-image-optimiser'); ?>: <i data-stats-custom="done">-</i></span>
89
 
90
+ <span><?php esc_html_e('Images Left', 'shortpixel-image-optimiser') ?>: <i data-stats-custom="in_queue">-</i></span>
91
+ <span><?php esc_html_e('Errors','shortpixel-image-optimiser') ?>: <i data-check-custom-fatalerrors data-stats-custom="fatal_errors" class='error'>-</i>
92
+ <span class="display-error-box" data-check-visibility data-control="data-check-custom-fatalerrors" ><label title="<?php esc_html_e('Show Errors', 'shortpixel-image-optimiser'); ?>">
93
  <input type="checkbox" name="show-errors" value="show" data-action='ToggleErrorBox' data-errorbox='custom' data-event='change'>Show Errors</label>
94
  </span>
95
  </span>
108
 
109
 
110
  <nav>
111
+ <button class='button finish' type="button" data-action="FinishBulk" id="FinishBulkButton"><?php esc_html_e('Finish Bulk Process','shortpixel-image-optimiser'); ?></button>
112
  </nav>
113
 
114
 
class/view/bulk/part-process.php CHANGED
@@ -1,15 +1,13 @@
1
  <?php
2
-
3
  namespace ShortPixel;
4
-
5
  ?>
6
  <section class="panel process" data-panel="process" >
7
  <div class="panel-container">
8
 
9
- <h3 class="heading"><span><img src="<?php echo \wpSPIO()->plugin_url('res/img/robo-slider.png'); ?>"></span>
10
- <?php _e('ShortPixel Bulk Process is in progress','shortpixel-image-optimiser'); ?>
11
  <div class='average-optimization'>
12
- <p><?php _e('Average this run','shortpixel-image-optimiser'); ?></p>
13
  <svg class="opt-circle-average" viewBox="-10 0 150 140">
14
  <path class="trail" d="
15
  M 50,50
@@ -25,13 +23,13 @@ namespace ShortPixel;
25
  a 46,46 0 1 1 0,-92
26
  " stroke-width="16" fill-opacity="0" style="stroke-dasharray: 289.027px, 289.027px; stroke-dashoffset: 180px;">
27
  </path>
28
- <text class="text" x="50" y="50"><?php _e('N/A', 'shortpixel-image-optimiser'); ?></text>
29
  </svg>
30
 
31
  </div>
32
  </h3>
33
 
34
- <p class='description'><?php _e('ShortPixel is processing your images. Please keep this window open to complete the process.', 'shortpixel-image-optimiser'); ?> </p>
35
 
36
  <?php $this->loadView('bulk/part-progressbar', false); ?>
37
 
@@ -39,7 +37,7 @@ namespace ShortPixel;
39
  <span class='hidden' data-check-media-total data-stats-media="total">0</span>
40
  <div class='bulk-summary' data-check-visibility data-control="data-check-media-total">
41
  <div class='heading'>
42
- <span><i class='dashicons dashicons-images-alt2'>&nbsp;</i> <?php _e('Media Library' ,'shortpixel-image-optimiser'); ?></span>
43
  <span>
44
  <span class='line-progressbar'>
45
  <span class='done-text'><i data-stats-media="percentage_done"></i> %</span>
@@ -49,17 +47,17 @@ namespace ShortPixel;
49
  <span class='dashicons spin dashicons-update line-progressbar-spinner' data-check-visibility data-control="data-check-media-in_process">&nbsp;</span>
50
 
51
  </span>
52
- <span><?php _e('Processing', 'shortpixel-image-optimiser') ?>: <i data-stats-media="in_process" data-check-media-in_process >-</i></span>
53
  </div>
54
 
55
  <div>
56
- <span><?php _e('Processed', 'shortpixel-image-optimiser'); ?>: <i data-stats-media="done">-</i></span>
57
 
58
- <span><?php _e('Waiting','shortpixel-image-optimiser'); ?>: <i data-stats-media="in_queue">-</i></span>
59
- <span><?php _e('Errors','shortpixel-image-optimiser') ?>: <i data-check-media-fatalerrors data-stats-media="fatal_errors" class='error'>- </i>
60
- <span class="display-error-box" data-check-visibility data-control="data-check-media-fatalerrors" ><label title="<?php _e('Show Errors', 'shortpixel-image-optimiser'); ?>">
61
  <input type="checkbox" name="show-errors" value="show" data-action='ToggleErrorBox' data-errorbox='media' data-event='change'>
62
- <?php _e('Show Errors','shortpixel-image-optimiser'); ?></label>
63
  </span>
64
 
65
  </span>
@@ -82,7 +80,7 @@ namespace ShortPixel;
82
 
83
  <div class='bulk-summary' data-check-visibility data-control="data-check-custom-total">
84
  <div class='heading'>
85
- <span><i class='dashicons dashicons-open-folder'>&nbsp;</i> <?php _e('Custom Media', 'shortpixel-image-optimiser'); ?> </span>
86
  <span>
87
  <span class='line-progressbar'>
88
  <span class='done-text'><i data-stats-custom="percentage_done"></i> %</span>
@@ -91,17 +89,17 @@ namespace ShortPixel;
91
  <span class='dashicons spin dashicons-update line-progressbar-spinner' data-check-visibility data-control="data-check-custom-in_process">&nbsp;</span>
92
 
93
  </span>
94
- <span><?php _e('Processing', 'shortpixel-image-optimiser') ?>: <i data-stats-custom="in_process" data-check-custom-in_process>-</i></span>
95
 
96
  </div>
97
  <div>
98
- <span><?php _e('Processed','shortpixel-image-optimiser'); ?>: <i data-stats-custom="done">-</i></span>
99
 
100
- <span><?php _e('Waiting','shortpixel-image-optimiser'); ?>: <i data-stats-custom="in_queue">-</i></span>
101
- <span><?php _e('Errors') ?>: <i data-check-custom-fatalerrors data-stats-custom="fatal_errors" class='error'>-</i>
102
 
103
- <span class="display-error-box" data-check-visibility data-control="data-check-custom-fatalerrors" ><label title="<?php _e('Show Errors', 'shortpixel-image-optimiser'); ?>">
104
- <input type="checkbox" name="show-errors" value="show" data-action='ToggleErrorBox' data-errorbox='custom' data-event='change'><?php _e('Show Errors','shortpixel-image-optimiser'); ?></label>
105
  </span>
106
  </span>
107
 
@@ -121,19 +119,19 @@ namespace ShortPixel;
121
 
122
  <nav>
123
  <button class='button stop' type='button' data-action="StopBulk" >
124
- <?php _e('Stop Bulk Processing' ,'shortpixel-image-optimiser'); ?>
125
  </button>
126
  <button class='button pause' type='button' data-action="PauseBulk" id="PauseBulkButton">
127
- <?php _e('Pause Bulk Processing' ,'shortpixel-image-optimiser') ?>
128
  </button>
129
  <button class='button button-primary resume' type='button' data-action='ResumeBulk' id="ResumeBulkButton">
130
- <?php _e('Resume Bulk Processing','shortpixel-image-optimiser'); ?>
131
  </button>
132
 
133
  </nav>
134
 
135
  <div class='image-preview-section hidden'> <!-- /hidden -->
136
- <div class='title'><?php _e('Just Optimized', 'shortpixel-image-optimiser'); ?></div>
137
  <div class="image-preview-line">
138
  <!-- <strong data-result="queuetype"></strong> -->
139
  <span>&nbsp;</span> <!-- Spacer for flex -->
@@ -159,18 +157,18 @@ namespace ShortPixel;
159
  </div>
160
 
161
  <div class="preview-wrapper">
162
- <div class="slide-mask" id="preview-structure" data-placeholder="<?php echo \wpSPIO()->plugin_url('res/img/bulk/placeholder.svg'); ?>">
163
 
164
  <div class='current preview-image'>
165
  <div class="image source">
166
- <img src="<?php echo \wpSPIO()->plugin_url('res/img/bulk/placeholder.svg'); ?>" >
167
- <p><?php _e('Original Image', 'shortpixel-image-optimiser'); ?></p>
168
  <?php $this->loadView('snippets/part-svgloader', false); ?>
169
  </div>
170
 
171
  <div class="image result">
172
- <img src="<?php echo \wpSPIO()->plugin_url('res/img/bulk/placeholder.svg'); ?>" >
173
- <p><?php _e('Optimized Image', 'shortpixel-image-optimiser'); ?></p>
174
  <?php $this->loadView('snippets/part-svgloader', false); ?>
175
  </div>
176
  </div>
@@ -178,15 +176,15 @@ namespace ShortPixel;
178
  <div class='new preview-image'>
179
 
180
  <div class="image source">
181
- <img src="<?php echo \wpSPIO()->plugin_url('res/img/bulk/placeholder.svg'); ?>" >
182
  <?php $this->loadView('snippets/part-svgloader', false); ?>
183
- <p><?php _e('Original Image','shortpixel-image-optimiser'); ?></p>
184
  </div>
185
 
186
  <div class="image result">
187
- <img src="<?php echo \wpSPIO()->plugin_url('res/img/bulk/placeholder.svg'); ?>" >
188
  <?php $this->loadView('snippets/part-svgloader', false); ?>
189
- <p><?php _e('Optimized Image','shortpixel-image-optimiser'); ?></p>
190
  </div>
191
  </div>
192
  </div> <!-- slidemask -->
@@ -195,8 +193,6 @@ namespace ShortPixel;
195
 
196
  <div id="preloader" class="hidden">
197
 
198
-
199
- </div>
200
-
201
 
202
  </section>
1
  <?php
 
2
  namespace ShortPixel;
 
3
  ?>
4
  <section class="panel process" data-panel="process" >
5
  <div class="panel-container">
6
 
7
+ <h3 class="heading"><span><img src="<?php echo esc_url(\wpSPIO()->plugin_url('res/img/robo-slider.png')); ?>"></span>
8
+ <?php esc_html_e('ShortPixel Bulk Process is in progress','shortpixel-image-optimiser'); ?>
9
  <div class='average-optimization'>
10
+ <p><?php esc_html_e('Average this run','shortpixel-image-optimiser'); ?></p>
11
  <svg class="opt-circle-average" viewBox="-10 0 150 140">
12
  <path class="trail" d="
13
  M 50,50
23
  a 46,46 0 1 1 0,-92
24
  " stroke-width="16" fill-opacity="0" style="stroke-dasharray: 289.027px, 289.027px; stroke-dashoffset: 180px;">
25
  </path>
26
+ <text class="text" x="50" y="50"><?php esc_html_e('N/A', 'shortpixel-image-optimiser'); ?></text>
27
  </svg>
28
 
29
  </div>
30
  </h3>
31
 
32
+ <p class='description'><?php esc_html_e('ShortPixel is processing your images. Please keep this window open to complete the process.', 'shortpixel-image-optimiser'); ?> </p>
33
 
34
  <?php $this->loadView('bulk/part-progressbar', false); ?>
35
 
37
  <span class='hidden' data-check-media-total data-stats-media="total">0</span>
38
  <div class='bulk-summary' data-check-visibility data-control="data-check-media-total">
39
  <div class='heading'>
40
+ <span><i class='dashicons dashicons-images-alt2'>&nbsp;</i> <?php esc_html_e('Media Library' ,'shortpixel-image-optimiser'); ?></span>
41
  <span>
42
  <span class='line-progressbar'>
43
  <span class='done-text'><i data-stats-media="percentage_done"></i> %</span>
47
  <span class='dashicons spin dashicons-update line-progressbar-spinner' data-check-visibility data-control="data-check-media-in_process">&nbsp;</span>
48
 
49
  </span>
50
+ <span><?php esc_html_e('Processing', 'shortpixel-image-optimiser') ?>: <i data-stats-media="in_process" data-check-media-in_process >-</i></span>
51
  </div>
52
 
53
  <div>
54
+ <span><?php esc_html_e('Processed', 'shortpixel-image-optimiser'); ?>: <i data-stats-media="done">-</i></span>
55
 
56
+ <span><?php esc_html_e('Waiting','shortpixel-image-optimiser'); ?>: <i data-stats-media="in_queue">-</i></span>
57
+ <span><?php esc_html_e('Errors','shortpixel-image-optimiser') ?>: <i data-check-media-fatalerrors data-stats-media="fatalesc_html_errors" class='error'>- </i>
58
+ <span class="display-error-box" data-check-visibility data-control="data-check-media-fatalerrors" ><label title="<?php esc_html_e('Show Errors', 'shortpixel-image-optimiser'); ?>">
59
  <input type="checkbox" name="show-errors" value="show" data-action='ToggleErrorBox' data-errorbox='media' data-event='change'>
60
+ <?php esc_html_e('Show Errors','shortpixel-image-optimiser'); ?></label>
61
  </span>
62
 
63
  </span>
80
 
81
  <div class='bulk-summary' data-check-visibility data-control="data-check-custom-total">
82
  <div class='heading'>
83
+ <span><i class='dashicons dashicons-open-folder'>&nbsp;</i> <?php esc_html_e('Custom Media', 'shortpixel-image-optimiser'); ?> </span>
84
  <span>
85
  <span class='line-progressbar'>
86
  <span class='done-text'><i data-stats-custom="percentage_done"></i> %</span>
89
  <span class='dashicons spin dashicons-update line-progressbar-spinner' data-check-visibility data-control="data-check-custom-in_process">&nbsp;</span>
90
 
91
  </span>
92
+ <span><?php esc_html_e('Processing', 'shortpixel-image-optimiser') ?>: <i data-stats-custom="in_process" data-check-custom-in_process>-</i></span>
93
 
94
  </div>
95
  <div>
96
+ <span><?php esc_html_e('Processed','shortpixel-image-optimiser'); ?>: <i data-stats-custom="done">-</i></span>
97
 
98
+ <span><?php esc_html_e('Waiting','shortpixel-image-optimiser'); ?>: <i data-stats-custom="in_queue">-</i></span>
99
+ <span><?php esc_html_e('Errors') ?>: <i data-check-custom-fatalerrors data-stats-custom="fatalesc_html_errors" class='error'>-</i>
100
 
101
+ <span class="display-error-box" data-check-visibility data-control="data-check-custom-fatalerrors" ><label title="<?php esc_html_e('Show Errors', 'shortpixel-image-optimiser'); ?>">
102
+ <input type="checkbox" name="show-errors" value="show" data-action='ToggleErrorBox' data-errorbox='custom' data-event='change'><?php esc_html_e('Show Errors','shortpixel-image-optimiser'); ?></label>
103
  </span>
104
  </span>
105
 
119
 
120
  <nav>
121
  <button class='button stop' type='button' data-action="StopBulk" >
122
+ <?php esc_html_e('Stop Bulk Processing' ,'shortpixel-image-optimiser'); ?>
123
  </button>
124
  <button class='button pause' type='button' data-action="PauseBulk" id="PauseBulkButton">
125
+ <?php esc_html_e('Pause Bulk Processing' ,'shortpixel-image-optimiser') ?>
126
  </button>
127
  <button class='button button-primary resume' type='button' data-action='ResumeBulk' id="ResumeBulkButton">
128
+ <?php esc_html_e('Resume Bulk Processing','shortpixel-image-optimiser'); ?>
129
  </button>
130
 
131
  </nav>
132
 
133
  <div class='image-preview-section hidden'> <!-- /hidden -->
134
+ <div class='title'><?php esc_html_e('Just Optimized', 'shortpixel-image-optimiser'); ?></div>
135
  <div class="image-preview-line">
136
  <!-- <strong data-result="queuetype"></strong> -->
137
  <span>&nbsp;</span> <!-- Spacer for flex -->
157
  </div>
158
 
159
  <div class="preview-wrapper">
160
+ <div class="slide-mask" id="preview-structure" data-placeholder="<?php echo esc_url(\wpSPIO()->plugin_url('res/img/bulk/placeholder.svg')); ?>">
161
 
162
  <div class='current preview-image'>
163
  <div class="image source">
164
+ <img src="<?php echo esc_url(\wpSPIO()->plugin_url('res/img/bulk/placeholder.svg')); ?>" >
165
+ <p><?php esc_html_e('Original Image', 'shortpixel-image-optimiser'); ?></p>
166
  <?php $this->loadView('snippets/part-svgloader', false); ?>
167
  </div>
168
 
169
  <div class="image result">
170
+ <img src="<?php echo esc_url(\wpSPIO()->plugin_url('res/img/bulk/placeholder.svg')); ?>" >
171
+ <p><?php esc_html_e('Optimized Image', 'shortpixel-image-optimiser'); ?></p>
172
  <?php $this->loadView('snippets/part-svgloader', false); ?>
173
  </div>
174
  </div>
176
  <div class='new preview-image'>
177
 
178
  <div class="image source">
179
+ <img src="<?php echo esc_url(\wpSPIO()->plugin_url('res/img/bulk/placeholder.svg')); ?>" >
180
  <?php $this->loadView('snippets/part-svgloader', false); ?>
181
+ <p><?php esc_html_e('Original Image','shortpixel-image-optimiser'); ?></p>
182
  </div>
183
 
184
  <div class="image result">
185
+ <img src="<?php echo esc_url(\wpSPIO()->plugin_url('res/img/bulk/placeholder.svg')); ?>" >
186
  <?php $this->loadView('snippets/part-svgloader', false); ?>
187
+ <p><?php esc_html_e('Optimized Image','shortpixel-image-optimiser'); ?></p>
188
  </div>
189
  </div>
190
  </div> <!-- slidemask -->
193
 
194
  <div id="preloader" class="hidden">
195
 
196
+ </div>
 
 
197
 
198
  </section>
class/view/bulk/part-progressbar.php CHANGED
@@ -9,22 +9,22 @@ namespace ShortPixel;
9
  <div class="select">
10
  <span class='line'></span>
11
  <span class="step">1</span>
12
- <span class="text"><?php _e('Select Images','shortpixel-image-optimiser'); ?></span>
13
  </div>
14
  <div class="summary">
15
  <span class='line'></span>
16
  <span class="step">2</span>
17
- <span class="text"><?php _e('Summary','shortpixel-image-optimiser'); ?></span>
18
  </div>
19
  <div class="process">
20
  <span class='line'></span>
21
  <span class="step">3</span>
22
- <span class="text"><?php _e('Bulk Process','shortpixel-image-optimiser'); ?></span>
23
  </div>
24
  <div class="result">
25
  <span class='line'></span>
26
  <span class="step">4</span>
27
- <span class="text"><?php _e('Results','shortpixel-image-optimiser'); ?></span>
28
  </div>
29
  </div>
30
 
9
  <div class="select">
10
  <span class='line'></span>
11
  <span class="step">1</span>
12
+ <span class="text"><?php esc_html_e('Select Images','shortpixel-image-optimiser'); ?></span>
13
  </div>
14
  <div class="summary">
15
  <span class='line'></span>
16
  <span class="step">2</span>
17
+ <span class="text"><?php esc_html_e('Summary','shortpixel-image-optimiser'); ?></span>
18
  </div>
19
  <div class="process">
20
  <span class='line'></span>
21
  <span class="step">3</span>
22
+ <span class="text"><?php esc_html_e('Bulk Process','shortpixel-image-optimiser'); ?></span>
23
  </div>
24
  <div class="result">
25
  <span class='line'></span>
26
  <span class="step">4</span>
27
+ <span class="text"><?php esc_html_e('Results','shortpixel-image-optimiser'); ?></span>
28
  </div>
29
  </div>
30
 
class/view/bulk/part-selection.php CHANGED
@@ -9,20 +9,20 @@ $approx = $this->view->approx;
9
  <?php echo ($this->view->approx->custom->has_custom === true) ? 1 : 0; ?>
10
  </span>
11
 
12
- <h3 class="heading"><span><img src="<?php echo \wpSPIO()->plugin_url('res/img/robo-slider.png'); ?>"></span>
13
- <?php _e('ShortPixel Bulk Optimization - Select Images', 'shortpixel-image-optimiser'); ?>
14
  </h3>
15
 
16
- <p class='description'><?php _e('Select the type of images that ShortPixel should optimize for you.','shortpixel-image-optimiser'); ?></p>
17
 
18
  <?php $this->loadView('bulk/part-progressbar', false); ?>
19
 
20
  <div class='load wrapper' >
21
  <div class='loading'>
22
- <span><img src="<?php echo \wpSPIO()->plugin_url('res/img/bulk/loading-hourglass.svg'); ?>" /></span>
23
  <span>
24
- <p><?php _e('Please wait, ShortPixel is checking the images to be processed...','shortpixel-image-optimiser'); ?><br>
25
- <span class="number" data-stats-total="total">x</span> items found</p>
26
  </span>
27
 
28
  </div>
@@ -32,8 +32,8 @@ $approx = $this->view->approx;
32
 
33
  <div class="option-block">
34
 
35
- <h2><?php _e('Optimize:','shortpixel-image-optimiser'); ?> </h2>
36
- <p><?php printf(__('ShortPixel has %sestimated%s the number of images that can still be optimized. %sAfter you select the options, the plugin will calculate exactly how many images to optimize.','shortpixel-image-optimiser'), '<b>','</b>', '<br />'); ?></p>
37
 
38
  <div class="media-library optiongroup">
39
 
@@ -45,14 +45,14 @@ $approx = $this->view->approx;
45
  </div>
46
 
47
 
48
- <h4><label for="media_checkbox"><?php _e('Media Library','shortpixel-image-optimiser'); ?></label></h4>
49
  <div class='option'>
50
- <label><?php _e('Images (estimate)', 'shortpixel-image-optimiser'); ?></label>
51
- <span class="number" ><?php echo $approx->media->items ?></span>
52
  </div>
53
  <?php if (\wpSPIO()->settings()->processThumbnails == 1): ?>
54
  <div class='option'>
55
- <label><?php _e('Thumbnails (estimate)','shortpixel-image-optimiser'); ?></label> <span class="number" ><?php echo $approx->media->thumbs ?> </span>
56
  </div>
57
  <?php endif; ?>
58
  </div>
@@ -66,14 +66,13 @@ $approx = $this->view->approx;
66
  <div class="the_switch">&nbsp; </div>
67
  </label>
68
  </div>
69
- <h4><label for="thumbnails_checkbox"><?php _e('Process Image Thumbnails','shortpixel-image-optimiser'); ?></label></h4>
70
  <div class='option'>
71
- <label><?php _e('Thumbnails (estimate)','shortpixel-image-optimiser'); ?></label> <span class="number" ><?php echo $approx->media->total ?> </span>
 
72
  </div>
73
 
74
- <p><?php _e('It is recommended to process the WordPress thumbnails. These are the small images that are most often used in posts and pages.This option changes the global ShortPixel settings of your site.','shortpixel-image-optimiser'); ?></p>
75
-
76
-
77
 
78
  </div>
79
  <?php endif; ?>
@@ -85,18 +84,18 @@ $approx = $this->view->approx;
85
  <div class="the_switch">&nbsp; </div>
86
  </label>
87
  </div>
88
- <h4><label for="custom_checkbox">Custom Media images</label></h4>
89
  <div class='option'>
90
- <label>Images (estimate)</label>
91
- <span class="number" ><?php echo $approx->custom->images ?></span>
92
  </div>
93
  </div>
94
  </div> <!-- block -->
95
 
96
  <div class="option-block selection-settings">
97
- <h2>Options: </h2>
98
- <p>Enable these options if you also want to create WebP/AVIF files. These options change the global ShortPixel settings of your site.</p>
99
- <div class='optiongroup ' >
100
  <div class='switch_button'>
101
 
102
  <label>
@@ -106,8 +105,10 @@ $approx = $this->view->approx;
106
  </label>
107
 
108
  </div>
109
- <h4><label for="webp_checkbox">Also create <b>WebP</b> versions of the images</label></h4>
110
- <div class="option">The total number of WebP images will be calculated in the next step.</div>
 
 
111
  </div>
112
 
113
  <div class='optiongroup'>
@@ -120,32 +121,32 @@ $approx = $this->view->approx;
120
  </label>
121
 
122
  </div>
123
- <h4><label for="avif_checkbox">Also create <b>AVIF</b> versions of the images</label></h4>
124
- <div class="option">The total number of AVIF images will be calculated in the next step.</div>
125
  </div>
126
  </div>
127
 
128
  <div class="option-block">
129
  <div class='optiongroup' data-check-visibility="false" data-control="data-check-approx-total">
130
- <h3><?php _e('No images found', 'shortpixel-image-optimiser'); ?></h3>
131
- <p><?php _e('ShortPixel Bulk couldn\'t find any optimizable images.','shortpixel-image-optimiser'); ?></p>
132
  </div>
133
 
 
 
134
 
135
- <h4 class='approx'><?php _e('An estimate of unoptimized images in this installation', 'shortpixel-image-optimiser'); ?> : <span data-check-approx-total><?php echo $approx->total->images ?></span> </h4>
136
-
137
- <div><p>In the next step, the plugin will calculate the total number of images to be optimized, and your bulk process will be prepared. The processing <b>will not start yet</b>, but a summary of the images to be optimized will be displayed.</p></div>
138
  </div>
139
 
140
  <nav>
141
  <button class="button" type="button" data-action="FinishBulk">
142
  <span class='dashicons dashicons-arrow-left'></span>
143
- <p><?php _e('Back', 'shortpixel-image-optimiser'); ?></p>
144
  </button>
145
 
146
  <button class="button-primary button" type="button" data-action="CreateBulk" data-panel="summary" data-check-disable data-control="data-check-total-total">
147
  <span class='dashicons dashicons-arrow-right'></span>
148
- <p><?php _e('Calculate', 'shortpixel-image-optimiser'); ?></p>
149
  </button>
150
  </nav>
151
 
9
  <?php echo ($this->view->approx->custom->has_custom === true) ? 1 : 0; ?>
10
  </span>
11
 
12
+ <h3 class="heading"><span><img src="<?php echo esc_url(\wpSPIO()->plugin_url('res/img/robo-slider.png')); ?>"></span>
13
+ <?php esc_html_e('ShortPixel Bulk Optimization - Select Images', 'shortpixel-image-optimiser'); ?>
14
  </h3>
15
 
16
+ <p class='description'><?php esc_html_e('Select the type of images that ShortPixel should optimize for you.','shortpixel-image-optimiser'); ?></p>
17
 
18
  <?php $this->loadView('bulk/part-progressbar', false); ?>
19
 
20
  <div class='load wrapper' >
21
  <div class='loading'>
22
+ <span><img src="<?php echo esc_url(\wpSPIO()->plugin_url('res/img/bulk/loading-hourglass.svg')); ?>" /></span>
23
  <span>
24
+ <p><?php esc_html_e('Please wait, ShortPixel is checking the images to be processed...','shortpixel-image-optimiser'); ?><br>
25
+ <span class="number" data-stats-total="total">x</span> <?php esc_html_e('items found', 'shortpixel-image-optimiser'); ?></p>
26
  </span>
27
 
28
  </div>
32
 
33
  <div class="option-block">
34
 
35
+ <h2><?php esc_html_e('Optimize:','shortpixel-image-optimiser'); ?> </h2>
36
+ <p><?php printf(esc_html__('ShortPixel has %sestimated%s the number of images that can still be optimized. %sAfter you select the options, the plugin will calculate exactly how many images to optimize.','shortpixel-image-optimiser'), '<b>','</b>', '<br />'); ?></p>
37
 
38
  <div class="media-library optiongroup">
39
 
45
  </div>
46
 
47
 
48
+ <h4><label for="media_checkbox"><?php esc_html_e('Media Library','shortpixel-image-optimiser'); ?></label></h4>
49
  <div class='option'>
50
+ <label><?php esc_html_e('Images (estimate)', 'shortpixel-image-optimiser'); ?></label>
51
+ <span class="number" ><?php echo esc_html($approx->media->items) ?></span>
52
  </div>
53
  <?php if (\wpSPIO()->settings()->processThumbnails == 1): ?>
54
  <div class='option'>
55
+ <label><?php esc_html_e('Thumbnails (estimate)','shortpixel-image-optimiser'); ?></label> <span class="number" ><?php echo esc_html($approx->media->thumbs) ?> </span>
56
  </div>
57
  <?php endif; ?>
58
  </div>
66
  <div class="the_switch">&nbsp; </div>
67
  </label>
68
  </div>
69
+ <h4><label for="thumbnails_checkbox"><?php esc_html_e('Process Image Thumbnails','shortpixel-image-optimiser'); ?></label></h4>
70
  <div class='option'>
71
+ <label><?php esc_html_e('Thumbnails (estimate)','shortpixel-image-optimiser'); ?></label>
72
+ <span class="number" ><?php echo esc_html($approx->media->total) ?> </span>
73
  </div>
74
 
75
+ <p><?php esc_html_e('It is recommended to process the WordPress thumbnails. These are the small images that are most often used in posts and pages.This option changes the global ShortPixel settings of your site.','shortpixel-image-optimiser'); ?></p>
 
 
76
 
77
  </div>
78
  <?php endif; ?>
84
  <div class="the_switch">&nbsp; </div>
85
  </label>
86
  </div>
87
+ <h4><label for="custom_checkbox"><?php esc_html_e('Custom Media images','shortpixel-image-optimiser') ?></label></h4>
88
  <div class='option'>
89
+ <label><?php esc_html_e('Images (estimate)','shortpixel-image-optimiser'); ?></label>
90
+ <span class="number" ><?php echo esc_html($approx->custom->images) ?></span>
91
  </div>
92
  </div>
93
  </div> <!-- block -->
94
 
95
  <div class="option-block selection-settings">
96
+ <h2><?php esc_html_e('Options','shortpixel-image-optimiser') ?>: </h2>
97
+ <p><?php esc_html_e('Enable these options if you also want to create WebP/AVIF files. These options change the global ShortPixel settings of your site.','shortpixel-image-optimiser'); ?></p>
98
+ <div class='optiongroup' >
99
  <div class='switch_button'>
100
 
101
  <label>
105
  </label>
106
 
107
  </div>
108
+ <h4><label for="webp_checkbox">
109
+ <?php printf(esc_html__('Also create %s WebP %s versions of the images' ,'shortpixel-image-optimiser'), '<b>', '</b>' ); ?>
110
+ </label></h4>
111
+ <div class="option"><?php esc_html_e('The total number of WebP images will be calculated in the next step.','shortpixel-image-optimiser'); ?></div>
112
  </div>
113
 
114
  <div class='optiongroup'>
121
  </label>
122
 
123
  </div>
124
+ <h4><label for="avif_checkbox"><?php esc_html_e('Also create AVIF> versions of the images','shortpixel-image-optimiser'); ?></label></h4>
125
+ <div class="option"><?php esc_html_e('The total number of AVIF images will be calculated in the next step.','shortpixel-image-optimiser'); ?></div>
126
  </div>
127
  </div>
128
 
129
  <div class="option-block">
130
  <div class='optiongroup' data-check-visibility="false" data-control="data-check-approx-total">
131
+ <h3><?php esc_html_e('No images found', 'shortpixel-image-optimiser'); ?></h3>
132
+ <p><?php esc_html_e('ShortPixel Bulk couldn\'t find any optimizable images.','shortpixel-image-optimiser'); ?></p>
133
  </div>
134
 
135
+ <h4 class='approx'><?php esc_html_e('An estimate of unoptimized images in this installation', 'shortpixel-image-optimiser'); ?> :
136
+ <span data-check-approx-total><?php echo esc_html($approx->total->images) ?></span> </h4>
137
 
138
+ <div><p><?php printf(esc_html_e('In the next step, the plugin will calculate the total number of images to be optimized, and your bulk process will be prepared. The processing %swill not start yet%s, but a summary of the images to be optimized will be displayed.', 'shortpixel-image-optimiser'),'<b>','</b>'); ?></p></div>
 
 
139
  </div>
140
 
141
  <nav>
142
  <button class="button" type="button" data-action="FinishBulk">
143
  <span class='dashicons dashicons-arrow-left'></span>
144
+ <p><?php esc_html_e('Back', 'shortpixel-image-optimiser'); ?></p>
145
  </button>
146
 
147
  <button class="button-primary button" type="button" data-action="CreateBulk" data-panel="summary" data-check-disable data-control="data-check-total-total">
148
  <span class='dashicons dashicons-arrow-right'></span>
149
+ <p><?php esc_html_e('Calculate', 'shortpixel-image-optimiser'); ?></p>
150
  </button>
151
  </nav>
152
 
class/view/bulk/part-summary.php CHANGED
@@ -5,54 +5,64 @@ namespace ShortPixel;
5
  <section class="panel summary" data-panel="summary">
6
  <div class="panel-container">
7
 
8
- <h3 class="heading"><span><img src="<?php echo \wpSPIO()->plugin_url('res/img/robo-slider.png'); ?>"></span>
9
- <?php _e('ShortPixel Bulk Optimization - Summary','shortpixel-image-optimiser'); ?>
10
  </h3>
11
 
12
- <p class='description'><?php _e('Welcome to the bulk optimization wizard, where you can select the images that ShortPixel will optimize in the background for you.','shortpixel-image-optimiser'); ?></p>
13
 
14
  <?php $this->loadView('bulk/part-progressbar', false); ?>
15
 
16
  <div class='summary-list'>
17
- <h3>Review and start the Bulk Process
18
- <span><img src="<?php echo wpSPIO()->plugin_url('res/img/bulk/robot-book-summary.svg') ?>" /></span>
19
  </h3>
20
  <div class="section-wrapper" data-check-visibility data-control="data-check-media-total">
21
- <h4><span class='dashicons dashicons-images-alt2'>&nbsp;</span> Media Library (<span data-stats-media="in_queue">0</span> items)</h4>
 
22
  <div class="list-table">
23
 
24
 
25
- <div><span>Images</span><span data-stats-media="images-images_basecount">n/a</span></div>
 
 
26
 
27
- <div class='filetypes' data-check-visibility data-control="data-check-has-webp"><span>&nbsp; + WebP images </span><span data-stats-media="images-images_webp" data-check-has-webp>&nbsp;</span></div>
28
- <div class='filetypes' data-check-visibility data-control="data-check-has-avif"><span>&nbsp; + AVIF images </span><span data-stats-media="images-images_avif" data-check-has-avif>&nbsp;</span></div>
 
 
 
 
29
 
30
 
31
- <div><span><?php _e('Total from Media Library','shortpixel-image-optimiser'); ?></span><span data-stats-media="images-images">0</span></div>
32
 
33
  </div>
34
  </div>
35
 
36
  <div class="section-wrapper" data-check-visibility data-control="data-check-custom-total">
37
- <h4><span class='dashicons dashicons-open-folder'>&nbsp;</span><?php _e('Custom Media', 'shortpixel-image-optimiser') ?> (<span data-stats-custom="in_queue">0</span> images)</h4>
38
  <div class="list-table">
39
- <div><span>Images</span><span data-stats-custom="images-images_basecount">n/a</span></div>
40
 
 
 
 
41
 
42
- <div class='filetypes' data-check-visibility data-control="data-check-has-custom-webp" ><span>&nbsp; + WebP images</span>
43
  <span data-stats-custom="images-images_webp" data-check-has-custom-webp>&nbsp;</span>
44
  </div>
 
45
  <div class='filetypes' data-check-visibility data-control="data-check-has-custom-avif">
46
- <span>&nbsp; + AVIF images</span><span data-stats-custom="images-images_avif" data-check-has-custom-avif>&nbsp;</span>
47
  </div>
48
 
49
- <div><span>Total from Custom Media</span><span data-stats-custom="images-images">0</span></div>
50
  </div>
51
  </div>
52
 
53
 
54
  <div class="totals">
55
- <?php _e('Total credits needed','shortpixel-image-optimiser') ?>: <span class="number" data-stats-total="images-images" data-check-total-total >0</span>
56
 
57
  <span class='number'></span>
58
  </div>
@@ -64,53 +74,54 @@ namespace ShortPixel;
64
  ?>
65
 
66
  <div class="credits">
67
- <p class='heading'><span><?php _e('Your ShortPixel Credits Available', 'shortpixel-image-optimiser'); ?></span>
68
- <span><?php echo $this->formatNumber($quotaData->total->remaining, 0) ?></span>
69
- <span><a href="<?php echo $this->view->buyMoreHref ?>" target="_new" class='button button-primary'>Buy more credits</a></span>
70
  </p>
71
 
72
- <p><span>Your monthly plan</span>
73
- <span><?php echo $quotaData->monthly->text ?> <br>
74
- <?php _e('Used:', 'shortpixel-image-optimiser'); ?> <?php echo $this->formatNumber($quotaData->monthly->consumed, 0); ?>
75
- <?php _e('; Remaining:', 'shortpixel-image-optimiser'); ?> <?php echo $this->formatNumber($quotaData->monthly->remaining, 0); ?>
76
  </span>
77
  </p>
78
 
79
  <p>
80
- <span>Your one-time credits</span>
81
- <span><?php echo $quotaData->onetime->text ?> <br>
82
- <?php _e('Used:', 'shortpixel-image-optimiser'); ?> <?php echo $this->formatNumber($quotaData->onetime->consumed, 0) ?>
83
- <?php _e('; Remaining:', 'shortpixel-image-optimiser'); ?> <?php echo $this->formatNumber($quotaData->onetime->remaining, 0) ?>
84
  </span>
85
  </p>
86
 
87
  </div>
88
 
89
  <div class="over-quota" data-check-visibility="false" data-control="data-quota-remaining" data-control-check="data-check-total-total">
90
- <span><img src="<?php echo wpSPIO()->plugin_url('res/img/bulk/over-quota.svg') ?>" /></span> <p>In your ShortPixel account you <span class='red'>have only <?php echo $this->formatNumber($quotaData->total->remaining, 0) ?> credits available </span>, but you have chosen <b data-stats-total="images-images">0</b> images to be optimized in this bulk process. You can either go back and select less images, or you can upgrade to a higher plan or buy one-time credits.
 
91
 
92
- <button type="button" class="button" onClick="ShortPixel.proposeUpgrade();">Show me the best options</button>
93
  </p>
94
 
95
  <span class='hidden' data-quota-remaining><?php
96
  // This is hidden check, no number format.
97
- echo $quotaData->total->remaining
98
  ?></span>
99
  </div>
100
  <?php $this->loadView('snippets/part-upgrade-options'); ?>
101
 
102
  <div class='no-images' data-check-visibility="false" data-control="data-check-total-total">
103
- <?php _e('The current selection contains no images. The bulk process cannot start.', 'shortpixel-image-optimiser'); ?>
104
  </div>
105
 
106
  <nav>
107
  <button class="button" type="button" data-action="open-panel" data-panel="selection">
108
  <span class='dashicons dashicons-arrow-left' ></span>
109
- <p><?php _e('Back','shortpixel-image-optimiser'); ?></p>
110
  </button>
111
  <button class="button-primary button" type="button" data-action="StartBulk" data-control="data-check-total-total" data-check-presentation="disable">
112
  <span class='dashicons dashicons-arrow-right'></span>
113
- <p><?php _e('Start Bulk Optimization', 'shortpixel-image-optimiser'); ?></p>
114
  </button>
115
  </nav>
116
  </div>
5
  <section class="panel summary" data-panel="summary">
6
  <div class="panel-container">
7
 
8
+ <h3 class="heading"><span><img src="<?php echo esc_url(\wpSPIO()->plugin_url('res/img/robo-slider.png')); ?>"></span>
9
+ <?php esc_html_e('ShortPixel Bulk Optimization - Summary','shortpixel-image-optimiser'); ?>
10
  </h3>
11
 
12
+ <p class='description'><?php esc_html_e('Welcome to the bulk optimization wizard, where you can select the images that ShortPixel will optimize in the background for you.','shortpixel-image-optimiser'); ?></p>
13
 
14
  <?php $this->loadView('bulk/part-progressbar', false); ?>
15
 
16
  <div class='summary-list'>
17
+ <h3><?php esc_html_e('Review and start the Bulk Process', 'shortpixel-image-optimiser'); ?>
18
+ <span><img src="<?php echo esc_url(wpSPIO()->plugin_url('res/img/bulk/robot-book-summary.svg')); ?>" /></span>
19
  </h3>
20
  <div class="section-wrapper" data-check-visibility data-control="data-check-media-total">
21
+ <h4><span class='dashicons dashicons-images-alt2'>&nbsp;</span>
22
+ <?php esc_html_e('Media Library','shortpixel-image-optimiser'); ?> (<span data-stats-media="in_queue">0</span> <?php esc_html_e('items','shortpixel-image-optimiser'); ?></h4>
23
  <div class="list-table">
24
 
25
 
26
+ <div><span><?php esc_html_e('Images','shortpixel-image-optimiser'); ?></span>
27
+ <span data-stats-media="images-images_basecount">n/a</span>
28
+ </div>
29
 
30
+ <div class='filetypes' data-check-visibility data-control="data-check-has-webp">
31
+ <span>&nbsp; <?php esc_html_e('+ WebP images','shortpixel-image-optimiser'); ?> </span><span data-stats-media="images-images_webp" data-check-has-webp>&nbsp;</span>
32
+ </div>
33
+ <div class='filetypes' data-check-visibility data-control="data-check-has-avif">
34
+ <span>&nbsp; <?php esc_html_e('+ AVIF images','shortpixel-image-optimiser'); ?> </span><span data-stats-media="images-images_avif" data-check-has-avif>&nbsp;</span>
35
+ </div>
36
 
37
 
38
+ <div><span><?php esc_html_e('Total from Media Library','shortpixel-image-optimiser'); ?></span><span data-stats-media="images-images">0</span></div>
39
 
40
  </div>
41
  </div>
42
 
43
  <div class="section-wrapper" data-check-visibility data-control="data-check-custom-total">
44
+ <h4><span class='dashicons dashicons-open-folder'>&nbsp;</span><?php esc_html_e('Custom Media', 'shortpixel-image-optimiser') ?> (<span data-stats-custom="in_queue">0</span> <?php esc_html_e('images','shortpixel-image-optimiser'); ?></h4>
45
  <div class="list-table">
 
46
 
47
+ <div><span><?php esc_html_e('Images','shortpixel-image-optimiser'); ?></span>
48
+ <span data-stats-custom="images-images_basecount">n/a</span>
49
+ </div>
50
 
51
+ <div class='filetypes' data-check-visibility data-control="data-check-has-custom-webp" ><span>&nbsp; <?php esc_html_e('+ WebP images','shortpixel-image-optimiser'); ?></span>
52
  <span data-stats-custom="images-images_webp" data-check-has-custom-webp>&nbsp;</span>
53
  </div>
54
+
55
  <div class='filetypes' data-check-visibility data-control="data-check-has-custom-avif">
56
+ <span>&nbsp; <?php esc_html_e('+ AVIF images','shortpixel-image-optimiser'); ?></span><span data-stats-custom="images-images_avif" data-check-has-custom-avif>&nbsp;</span>
57
  </div>
58
 
59
+ <div><span><?php esc_html_e('Total from Custom Media','shortpixel-image-optimiser'); ?></span><span data-stats-custom="images-images">0</span></div>
60
  </div>
61
  </div>
62
 
63
 
64
  <div class="totals">
65
+ <?php esc_html_e('Total credits needed','shortpixel-image-optimiser') ?>: <span class="number" data-stats-total="images-images" data-check-total-total >0</span>
66
 
67
  <span class='number'></span>
68
  </div>
74
  ?>
75
 
76
  <div class="credits">
77
+ <p class='heading'><span><?php esc_html_e('Your ShortPixel Credits Available', 'shortpixel-image-optimiser'); ?></span>
78
+ <span><?php echo esc_html($this->formatNumber($quotaData->total->remaining, 0)) ?></span>
79
+ <span><a href="<?php echo esc_url($this->view->buyMoreHref) ?>" target="_new" class='button button-primary'><?php esc_html_e('Buy more credits','shortpixel-image-optimiser'); ?></a></span>
80
  </p>
81
 
82
+ <p><span><?php esc_html_e('Your monthly plan','shortpixel-image-optimiser'); ?></span>
83
+ <span><?php echo esc_html($quotaData->monthly->text) ?> <br>
84
+ <?php esc_html_e('Used:', 'shortpixel-image-optimiser'); ?> <?php echo esc_html($this->formatNumber($quotaData->monthly->consumed, 0)); ?>
85
+ <?php esc_html_e('; Remaining:', 'shortpixel-image-optimiser'); ?> <?php echo esc_html($this->formatNumber($quotaData->monthly->remaining, 0)); ?>
86
  </span>
87
  </p>
88
 
89
  <p>
90
+ <span><?php esc_html_e('Your one-time credits') ?></span>
91
+ <span><?php echo esc_html($quotaData->onetime->text) ?> <br>
92
+ <?php esc_html_e('Used:', 'shortpixel-image-optimiser'); ?> <?php echo esc_html($this->formatNumber($quotaData->onetime->consumed, 0)); ?>
93
+ <?php esc_html_e('; Remaining:', 'shortpixel-image-optimiser'); ?> <?php echo esc_html($this->formatNumber($quotaData->onetime->remaining, 0)) ?>
94
  </span>
95
  </p>
96
 
97
  </div>
98
 
99
  <div class="over-quota" data-check-visibility="false" data-control="data-quota-remaining" data-control-check="data-check-total-total">
100
+ <span><img src="<?php echo esc_url(wpSPIO()->plugin_url('res/img/bulk/over-quota.svg')) ?>" /></span>
101
+ <p><?php printf(esc_html_e('In your ShortPixel account you %shave only %s credits available %s, but you have chosen %s images to be optimized in this bulk process. You can either go back and select less images, or you can upgrade to a higher plan or buy one-time credits.','shortpixel-image-optimiser'), '<span class="red">', esc_html($this->formatNumber($quotaData->total->remaining, 0)), '</span>', '<b data-stats-total="images-images">0</b>'); ?>
102
 
103
+ <button type="button" class="button" onClick="ShortPixel.proposeUpgrade();"><?php esc_html_e('Show me the best options') ?></button>
104
  </p>
105
 
106
  <span class='hidden' data-quota-remaining><?php
107
  // This is hidden check, no number format.
108
+ echo esc_html($quotaData->total->remaining);
109
  ?></span>
110
  </div>
111
  <?php $this->loadView('snippets/part-upgrade-options'); ?>
112
 
113
  <div class='no-images' data-check-visibility="false" data-control="data-check-total-total">
114
+ <?php esc_html_e('The current selection contains no images. The bulk process cannot start.', 'shortpixel-image-optimiser'); ?>
115
  </div>
116
 
117
  <nav>
118
  <button class="button" type="button" data-action="open-panel" data-panel="selection">
119
  <span class='dashicons dashicons-arrow-left' ></span>
120
+ <p><?php esc_html_e('Back','shortpixel-image-optimiser'); ?></p>
121
  </button>
122
  <button class="button-primary button" type="button" data-action="StartBulk" data-control="data-check-total-total" data-check-presentation="disable">
123
  <span class='dashicons dashicons-arrow-right'></span>
124
+ <p><?php esc_html_e('Start Bulk Optimization', 'shortpixel-image-optimiser'); ?></p>
125
  </button>
126
  </nav>
127
  </div>
class/view/settings/part-advanced.php CHANGED
@@ -3,10 +3,8 @@ namespace ShortPixel;
3
  use \ShortPixel\Helper\UiHelper as UiHelper;
4
 
5
  ?>
6
-
7
-
8
- <section id="tab-adv-settings" class="clearfix <?php echo ($this->display_part == 'adv-settings') ? ' sel-tab ' :''; ?> ">
9
- <h2><a class='tab-link' href='javascript:void(0);' data-id="tab-adv-settings"><?php _e('Advanced','shortpixel-image-optimiser');?></a></h2>
10
 
11
  <?php
12
  $deliverWebpAlteredDisabled = '';
@@ -29,11 +27,11 @@ use \ShortPixel\Helper\UiHelper as UiHelper;
29
  } else {
30
  $deliverWebpUnalteredLabel = __('It looks like your .htaccess file cannot be written. Please fix this and then return to refresh this page to enable this option.','shortpixel-image-optimiser');
31
  }
32
- } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Chrome') !== false) {
33
  // Show a message about the risks and caveats of serving WEBP images via .htaccess
34
- $deliverWebpUnalteredLabel = '<span style="color: initial;">'.__('Based on testing your particular hosting configuration, we determined that your server','shortpixel-image-optimiser').
35
- '&nbsp;<img alt="can or can not" src="'. plugins_url( 'res/img/test.jpg' , SHORTPIXEL_PLUGIN_FILE) .'">&nbsp;'.
36
- __('serve the WebP or AVIF versions of the JPEG files seamlessly, via .htaccess.','shortpixel-image-optimiser').' <a href="https://shortpixel.com/knowledge-base/article/127-delivering-webp-images-via-htaccess" target="_blank" data-beacon-article="5c1d050e04286304a71d9ce4">Open article to read more about this.</a></span>';
37
  }
38
  }
39
 
@@ -53,14 +51,14 @@ use \ShortPixel\Helper\UiHelper as UiHelper;
53
  <table class="form-table">
54
  <tbody>
55
  <tr>
56
- <th scope="row"><?php _e('Next Generation Images','shortpixel-image-optimiser');?></th>
57
  <td>
58
  <div class='switch_button'>
59
  <div class="spio-inline-help"><span class="dashicons dashicons-editor-help" title="Click for more info" data-link="https://shortpixel.com/knowledge-base/article/286-how-to-serve-webp-files-using-spio"></span></div>
60
  <label>
61
  <input type="checkbox" class="switch" name="createWebp" value="1" <?php checked( $view->data->createWebp, "1" );?>>
62
  <div class="the_switch">&nbsp; </div>
63
- <?php _e('Create <a href="https://shortpixel.com/blog/how-webp-images-can-speed-up-your-site/" target="_blank">WebP versions</a> of the images, with the additional cost of 1 credit = 1 image or thumbnail.','shortpixel-image-optimiser');?>
64
  </label>
65
  </div>
66
 
@@ -71,14 +69,14 @@ use \ShortPixel\Helper\UiHelper as UiHelper;
71
  <label>
72
  <input type="checkbox" class="switch" name="createAvif" value="1" <?php checked( $view->data->createAvif, "1" );?>>
73
  <div class="the_switch">&nbsp; </div>
74
- <?php _e('Create <a href="https://shortpixel.com/blog/what-is-avif-and-why-is-it-good/" target="_blank">AVIF versions</a> of the images, with the additional cost of 1 credit = 1 image or thumbnail.','shortpixel-image-optimiser');?>
75
  </label>
76
  </div>
77
 
78
 
79
  <?php if($deliverAVIFLabel || true){ ?>
80
  <p class="sp-notice">
81
- <?php echo( $deliverAVIFLabel );?>
82
  </p>
83
  <?php } ?>
84
 
@@ -90,49 +88,49 @@ use \ShortPixel\Helper\UiHelper as UiHelper;
90
  <label>
91
  <input type="checkbox" class="switch" name="deliverWebp" data-toggle="deliverTypes" value="1" <?php checked( ($view->data->deliverWebp > 0), true);?>>
92
  <div class="the_switch">&nbsp; </div>
93
- <?php _e('Deliver the next generation versions of the images in the front-end:','shortpixel-image-optimiser');?>
94
  </label>
95
  </div>
96
 
97
 
98
  <ul class="deliverWebpTypes toggleTarget" id="deliverTypes">
99
  <li>
100
- <input type="radio" name="deliverWebpType" id="deliverWebpAltered" <?php checked( ($view->data->deliverWebp >= 1 && $view->data->deliverWebp <= 2), true); ?> <?php echo( $deliverWebpAlteredDisabled );?> value="deliverWebpAltered" data-toggle="deliverAlteringTypes">
101
  <label for="deliverWebpAltered">
102
- <?php _e('Using the &lt;PICTURE&gt; tag syntax','shortpixel-image-optimiser');?>
103
  </label>
104
 
105
  <?php if($deliverWebpAlteredDisabledNotice){ ?>
106
  <p class="sp-notice">
107
- <?php _e('After the option to work on .htaccess was selected, the .htaccess file has become unaccessible / read-only. Please make the .htaccess file writeable again to be able to further set this option up.','shortpixel-image-optimiser')?>
108
  </p>
109
  <?php } ?>
110
 
111
  <p class="settings-info">
112
- <?php _e('Each &lt;img&gt; will be replaced with a &lt;picture&gt; tag that will also provide AVIF and WebP images for browsers that support it. Also, it loads the picturefill.js for browsers that don\'t support the &lt;picture&gt; tag. You don\'t need to activate this if you\'re using the Cache Enabler plugin because your AVIF\WebP images are already handled by this plugin. <strong>Please run some tests before using this option!</strong> If the styles that your theme is using rely on the position of your &lt;img&gt; tags, you may experience display problems.','shortpixel-image-optimiser'); ?>
113
- <strong><?php _e('You can revert anytime to the previous state just by deactivating the option.','shortpixel-image-optimiser'); ?></strong>
114
  </p>
115
 
116
  <ul class="deliverWebpAlteringTypes toggleTarget" id="deliverAlteringTypes">
117
  <li>
118
  <input type="radio" name="deliverWebpAlteringType" id="deliverWebpAlteredWP" <?php checked(($view->data->deliverWebp == 2), true);?> value="deliverWebpAlteredWP">
119
  <label for="deliverWebpAlteredWP">
120
- <?php _e('Only via Wordpress hooks (like the_content, the_excerpt, etc)');?>
121
  </label>
122
  </li>
123
  <li>
124
  <input type="radio" name="deliverWebpAlteringType" id="deliverWebpAlteredGlobal" <?php checked(($view->data->deliverWebp == 1),true)?> value="deliverWebpAlteredGlobal">
125
  <label for="deliverWebpAlteredGlobal">
126
- <?php _e('Global (processes the whole output buffer before sending the HTML to the browser)','shortpixel-image-optimiser');?>
127
  </label>
128
  </li>
129
  </ul>
130
  </li>
131
  <li>
132
- <input type="radio" name="deliverWebpType" id="deliverWebpUnaltered" <?php checked(($view->data->deliverWebp == 3), true);?> <?php echo( $deliverWebpUnalteredDisabled );?> value="deliverWebpUnaltered" data-toggle="deliverAlteringTypes" data-toggle-reverse>
133
 
134
  <label for="deliverWebpUnaltered">
135
- <?php _e('Without altering the page code (via .htaccess)','shortpixel-image-optimiser')?>
136
  </label>
137
  <?php if($deliverWebpUnalteredLabel){ ?>
138
  <p class="sp-notice"><strong>
@@ -146,7 +144,7 @@ use \ShortPixel\Helper\UiHelper as UiHelper;
146
  </td>
147
  </tr>
148
  <tr>
149
- <th scope="row"><?php _e('Optimize media on upload','shortpixel-image-optimiser');?></th>
150
  <td>
151
 
152
  <div class='switch_button'>
@@ -154,7 +152,7 @@ use \ShortPixel\Helper\UiHelper as UiHelper;
154
  <label>
155
  <input type="checkbox" class="switch" name="autoMediaLibrary" id='autoMediaLibrary' value="1" <?php checked( $view->data->autoMediaLibrary, "1" );?>>
156
  <div class="the_switch">&nbsp; </div>
157
- <?php _e('Automatically optimize images after they are uploaded (recommended).','shortpixel-image-optimiser');?>
158
  </label>
159
  </div>
160
  </td>
@@ -166,10 +164,10 @@ use \ShortPixel\Helper\UiHelper as UiHelper;
166
 
167
 
168
  <tr id="frontBootstrapRow">
169
- <th scope="row"><?php _e('Process in the front-end','shortpixel-image-optimiser');?></th>
170
  <td>
171
  <input name="frontBootstrap" type="checkbox" id="frontBootstrap" value="1" <?php checked( $view->data->frontBootstrap, '1' );?>>
172
- <label for="frontBootstrap"><?php _e('Automatically optimize images added by users in front-end of the site.','shortpixel-image-optimiser');?></label>
173
 
174
  </td>
175
  </tr>
@@ -177,8 +175,8 @@ use \ShortPixel\Helper\UiHelper as UiHelper;
177
  <th scope='row'>&nbsp;</th>
178
  <td>
179
  <div class="spio-inline-help"><span class="dashicons dashicons-editor-help" title="Click for more info" data-link="https://shortpixel.helpscoutdocs.com/article/536-why-is-the-option-process-in-the-front-end-gone"></span></div>
180
- <div class='view-notice warning'><p><?php _e('Important. From version 5 the front processing option is no longer available. There will be no processing on the frontend. To enable optimizing images without visiting the backend, please see the options available for command line optimization.', 'shortpixel-image-optimiser') ?></p>
181
- <p><?php _e('To turn off this message, click the checkbox and save settings', 'shortpixel-image-optimiser'); ?></p>
182
  </div>
183
  </td>
184
  </tr>
@@ -189,14 +187,14 @@ use \ShortPixel\Helper\UiHelper as UiHelper;
189
 
190
  <?php if($this->has_nextgen) { ?>
191
  <tr>
192
- <th scope="row"><?php _e('NextGen','shortpixel-image-optimiser');?></th>
193
  <td>
194
  <div class='switch_button'>
195
  <label>
196
  <input name="includeNextGen" type="checkbox" id="nextGen" value='1' <?php echo checked($view->data->includeNextGen,'1' );?>>
197
 
198
  <div class="the_switch">&nbsp; </div>
199
- <?php _e('Optimize NextGen galleries.','shortpixel-image-optimiser');?>
200
  </label>
201
  </div>
202
 
@@ -204,7 +202,7 @@ use \ShortPixel\Helper\UiHelper as UiHelper;
204
  </tr>
205
  <?php } ?>
206
  <tr>
207
- <th scope="row"><?php _e('Optimize PDFs','shortpixel-image-optimiser');?></th>
208
  <td>
209
  <div class='switch_button'>
210
  <div class="spio-inline-help"><span class="dashicons dashicons-editor-help" title="Click for more info" data-link="https://shortpixel.com/knowledge-base/article/520-settings-optimize-pdfs"></span></div>
@@ -212,27 +210,27 @@ use \ShortPixel\Helper\UiHelper as UiHelper;
212
  <label>
213
  <input type="checkbox" class="switch" name="optimizePdfs" value="1" <?php checked( $view->data->optimizePdfs, "1" );?>>
214
  <div class="the_switch">&nbsp; </div>
215
- <?php _e('Also optimize PDF documents.','shortpixel-image-optimiser');?>
216
  </label>
217
  </div>
218
 
219
  </td>
220
  </tr>
221
  <tr>
222
- <th scope="row"><?php _e('Optimize Retina images','shortpixel-image-optimiser');?></th>
223
  <td>
224
  <div class='switch_button'>
225
  <div class="spio-inline-help"><span class="dashicons dashicons-editor-help" title="Click for more info" data-link="https://shortpixel.com/knowledge-base/article/518-settings-optimize-retina-images"></span></div>
226
  <label>
227
  <input type="checkbox" class="switch" name="optimizeRetina" value="1" <?php checked( $view->data->optimizeRetina, "1" );?>>
228
  <div class="the_switch">&nbsp; </div>
229
- <?php _e('Also optimize the Retina images (@2x) if they exist.','shortpixel-image-optimiser');?>
230
  </label>
231
  </div>
232
  </td>
233
  </tr>
234
  <tr>
235
- <th scope="row"><?php _e('Optimize other thumbnails','shortpixel-image-optimiser');?></th>
236
  <td>
237
 
238
 
@@ -241,25 +239,28 @@ use \ShortPixel\Helper\UiHelper as UiHelper;
241
  <label>
242
  <input type="checkbox" class="switch" name="optimizeUnlisted" value="1" <?php checked( $view->data->optimizeUnlisted, "1" );?>>
243
  <div class="the_switch">&nbsp; </div>
244
- <?php _e('Also optimize unlisted thumbnails, if found.','shortpixel-image-optimiser');?>
245
  </label>
246
  </div>
247
  </td>
248
  </tr>
249
  <tr>
250
- <th scope="row"><?php _e('Convert PNG images to JPEG','shortpixel-image-optimiser');?></th>
251
  <td>
252
  <div class='switch_button option-png2jpg'>
253
  <div class="spio-inline-help"><span class="dashicons dashicons-editor-help" title="Click for more info" data-link="https://shortpixel.com/knowledge-base/article/516-settings-convert-png-images-to-jpeg"></span></div>
254
  <label>
255
  <input type="checkbox" class="switch" name="png2jpg" value="1" <?php checked( ($view->data->png2jpg > 0), true);?> <?php echo($this->is_gd_installed ? '' : 'disabled') ?> data-toggle="png2jpgforce">
256
  <div class="the_switch">&nbsp; </div>
257
- <?php _e('Automatically convert the PNG images to JPEG, if possible.','shortpixel-image-optimiser'); ?>
258
  </label>
259
  </div>
260
 
261
- <?php if(!$this->is_gd_installed) {echo("&nbsp;<div style='color:red;'>" . __('You need PHP GD with support for JPEG and PNG files for this feature. Please ask your hosting provider to install it.','shortpixel-image-optimiser') . "</div>"); }
262
- ?>
 
 
 
263
 
264
 
265
  <div class='switch_button option-png2jpgforce toggleTarget suboption' id="png2jpgforce">
@@ -267,7 +268,7 @@ use \ShortPixel\Helper\UiHelper as UiHelper;
267
  <label>
268
  <input type="checkbox" class="switch" name="png2jpgForce" value="1" <?php checked(($view->data->png2jpg > 1), true);?> <?php echo($this->is_gd_installed ? '' : 'disabled') ?>>
269
  <div class="the_switch">&nbsp; </div>
270
- <?php _e('Also force the conversion of images with transparency.','shortpixel-image-optimiser'); ?>
271
  </label>
272
  </div>
273
 
@@ -276,25 +277,25 @@ use \ShortPixel\Helper\UiHelper as UiHelper;
276
  <tr class='exif_warning view-notice-row'>
277
  <th scope="row">&nbsp;</th>
278
  <td>
279
- <div class='view-notice warning'><p><?php printf(__('Warning - Converting from PNG to JPG will %s not %s keep the EXIF information!', 'shortpixel-image-optimiser'), "<strong>","</strong>"); ?></p></div>
280
  </td>
281
  </tr>
282
  <tr>
283
- <th scope="row"><?php _e('CMYK to RGB conversion','shortpixel-image-optimiser');?></th>
284
  <td>
285
  <div class='switch_button'>
286
  <div class="spio-inline-help"><span class="dashicons dashicons-editor-help" title="Click for more info" data-link="https://shortpixel.com/knowledge-base/article/517-settings---cmyk-to-rgb-conversion"></span></div>
287
  <label>
288
  <input type="checkbox" class="switch" name="cmyk2rgb" value="1" <?php checked( $view->data->CMYKtoRGBconversion, "1" );?>>
289
  <div class="the_switch">&nbsp; </div>
290
- <?php _e('Adjust your images\' colors for computer and mobile displays.','shortpixel-image-optimiser');?>
291
  </label>
292
  </div>
293
 
294
  </td>
295
  </tr>
296
  <tr>
297
- <th scope="row"><label for="excludeSizes"><?php _e('Exclude thumbnail sizes','shortpixel-image-optimiser');?></label></th>
298
  <td>
299
  <div class="option-content">
300
  <div class="spio-inline-help"><span class="dashicons dashicons-editor-help" title="Click for more info" data-link="https://shortpixel.com/knowledge-base/article/113-how-can-i-optimize-only-certain-thumbnail-sizes"></span></div>
@@ -304,8 +305,10 @@ use \ShortPixel\Helper\UiHelper as UiHelper;
304
  <span style="margin-right: 20px;white-space:nowrap">
305
  <label>
306
 
307
- <input name="excludeSizes[]" type="checkbox" id="excludeSizes_<?php echo($sizeKey);?>" <?php echo((in_array($sizeKey, $view->data->excludeSizes) ? 'checked' : ''));?>
308
- value="<?php echo($sizeKey);?>">&nbsp;<?php $w=$sizeVal['width']?$sizeVal['width'].'px':'*';$h=$sizeVal['height']?$sizeVal['height'].'px':'*';echo("$sizeKey ({$w} &times; {$h})");?>&nbsp;&nbsp;
 
 
309
  </label>
310
  </span><br>
311
  <?php } ?>
@@ -313,44 +316,74 @@ use \ShortPixel\Helper\UiHelper as UiHelper;
313
  </td>
314
  </tr>
315
  <tr>
316
- <th scope="row"><label for="excludePatterns"><?php _e('Exclude patterns','shortpixel-image-optimiser');?></label></th>
317
  <td>
318
  <div class="option-content">
319
  <div class="spio-inline-help"><span class="dashicons dashicons-editor-help" title="Click for more info" data-link="https://shortpixel.com/knowledge-base/article/88-how-to-exclude-images-from-being-optimized"></span></div>
320
 
321
  <textarea name="excludePatterns" type="text" id="excludePatterns" placeholder="<?php
322
- _e('name:keepbig, path:/full/path/to/exclude/, regex-name:/valid_regex/, size:1000x2000','shortpixel-image-optimiser');?>" rows="4" cols="60"><?php echo( $excludePatterns );?></textarea>
323
 
324
  </div>
325
  <p class="settings-info">
326
- <?php _e('Add patterns separated by comma. A pattern consist of a <strong>type:value</strong> pair; the accepted types are
327
- <strong>"name"</strong>, <strong>"path"</strong>, <strong>"size"</strong>, <strong>"regex-name"</strong> and <strong>"regex-path"</strong>.
328
- A file is excluded if it matches any of the patterns. <br>
329
- <br>For a <strong>"name"</strong> pattern only the filename is matched, for <strong>"path"</strong>,
 
 
 
330
  the whole path will be matched (useful for excluding certain (sub)-directories altoghether).
331
- <br><br>
332
- <strong>"regex-path"</strong> and <strong>"regex-name"</strong> work the same, except it requires a valid regular expression, contained between slashes. Special characters should be escaped by adding \ in front of them.
333
- <br>
334
- <br>For the <strong>"size"</strong> type,
335
- which applies only to Media Library images, <strong>the main images (not thumbnails)</strong> that have the size in the specified range are excluded.
336
- The format for the "size" exclude is: <strong>minWidth</strong>-<strong>maxWidth</strong>x<strong>minHeight</strong>-<strong>maxHeight</strong>, for example <strong>size:1000-1100x2000-2200</strong>. You can also specify a precise size, such as <strong>1000x2000</strong>.','shortpixel-image-optimiser');?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
337
  </p>
338
  </td>
339
  </tr>
340
  <tr>
341
- <th scope="row"><label for="additional-media"><?php _e('Custom media folders','shortpixel-image-optimiser');?></label></th>
342
  <td>
343
- <span style="display:none;">Current PHP version: <?php echo(phpversion()) ?></span>
344
  <?php if($view->customFolders) { ?>
345
 
346
  <div class="option-content">
347
  <div class="spio-inline-help"><span class="dashicons dashicons-editor-help" title="Click for more info" data-link="https://shortpixel.com/knowledge-base/article/46-how-to-optimize-images-in-wordpress-themes-and-plugins"></span></div>
348
  <div class="shortpixel-folders-list">
349
  <div class='heading'>
350
- <span><?php _e('Folder name','shortpixel-image-optimiser');?></span>
351
- <span><?php _e('Type &amp; Status','shortpixel-image-optimiser');?></span>
352
- <span><?php _e('Files','shortpixel-image-optimiser');?></span>
353
- <span><?php _e('Last change','shortpixel-image-optimiser');?></span>
354
  <span>&nbsp;</span>
355
  <span class='action'>&nbsp;</span>
356
  </div>
@@ -361,11 +394,10 @@ use \ShortPixel\Helper\UiHelper as UiHelper;
361
 
362
 
363
  $type_display = ($dirObj->get('is_nextgen') ) ? __('Nextgen', 'shortpixel-image-optimiser') . "<br>" : "";
364
- // $stat = $this->shortPixel->getSpMetaDao()->getFolderOptimizationStatus($folder->getId());
365
  $stat = $dirObj->getStats();
366
 
367
- $fullstatus = __("Optimized",'shortpixel-image-optimiser') . ": " . $stat->Optimized . ", "
368
- . " " . __("Waiting",'shortpixel-image-optimiser') . ": " . $stat->Waiting . ""
369
  ;
370
 
371
  if ($stat->Total == 0)
@@ -387,7 +419,7 @@ use \ShortPixel\Helper\UiHelper as UiHelper;
387
  }
388
 
389
  $action = __("Stop monitoring",'shortpixel-image-optimiser');
390
- /*$err = $stat->Failed > 0 && !$st == __("Empty",'shortpixel-image-optimiser') ? " ({$stat->Failed} failed)" : false; */
391
  $err = ''; // unused since failed is gone.
392
  if (! $dirObj->exists() && ! $err)
393
  $err = __('Directory does not exist', 'shortpixel-image-optimiser');
@@ -400,27 +432,27 @@ use \ShortPixel\Helper\UiHelper as UiHelper;
400
  $refreshUrl = add_query_arg(array('sp-action' => 'action_refreshfolder', 'folder_id' => $folder_id, 'part' => 'adv-settings'), $this->url); // has url
401
  ?>
402
  <div>
403
- <span class='folder folder-<?php echo $dirObj->get('id') ?>'><?php echo($dirObj->getPath()); ?></span>
404
  <span>
405
  <?php if(!($stat->Total == 0)) { ?>
406
- <span title="<?php echo $fullstatus; ?>" class='info-icon'>
407
- <img alt='<?php _e('Info Icon', 'shortpixel-image-optimiser') ?>' src='<?php echo( wpSPIO()->plugin_url('res/img/info-icon.png' ));?>' style="margin-bottom: -2px;"/>
408
  </span>&nbsp;<?php }
409
- echo($type_display. ' ' . $optimize_status. '<br>' . $err);
410
  ?>
411
  </span>
412
  <span>
413
- <?php echo($stat->Total); ?> files
414
  </span>
415
  <span>
416
- <?php echo UiHelper::formatTS($dirObj->get('updated')) ?>
417
  </span>
418
  <span>
419
- <a href='<?php echo $refreshUrl ?>' title="<?php _e('Recheck for new images', 'shortpixel-image-optimiser'); ?>" class='refresh-folder'><i class='dashicons dashicons-update'>&nbsp;</i></a>
420
  </span>
421
  <span class='action'>
422
  <?php if ($action): ?>
423
- <input type="button" class="button remove-folder-button" data-value="<?php echo($dirObj->get('id')); ?>" data-name="<?php echo $dirObj->getPath() ?>" title="<?php echo($action . " " . $dirObj->getPath()); ?>" value="<?php echo $action;?>">
424
  <?php endif; ?>
425
  </span>
426
  </div>
@@ -432,25 +464,25 @@ use \ShortPixel\Helper\UiHelper as UiHelper;
432
  <div class='addCustomFolder'>
433
 
434
  <input type="hidden" name="removeFolder" id="removeFolder"/>
435
- <p class='add-folder-text'><strong><?php _e('Add a custom folder', 'shortpixel-image-optimiser'); ?></strong></p>
436
  <input type="text" name="addCustomFolderView" id="addCustomFolderView" class="regular-text" value="" disabled style="">&nbsp;
437
  <input type="hidden" name="addCustomFolder" id="addCustomFolder" value=""/>
438
- <input type="hidden" id="customFolderBase" value="<?php echo $this->view->customFolderBase; ?>">
439
 
440
- <a class="button select-folder-button" title="<?php _e('Select the images folder on your server.','shortpixel-image-optimiser');?>" href="javascript:void(0);">
441
- <?php _e('Select','shortpixel-image-optimiser');?>
442
  </a>
443
- <input type="submit" name="save" id="saveAdvAddFolder" class="button button-primary hidden" title="<?php _e('Add this Folder','shortpixel-image-optimiser');?>" value="<?php _e('Add this Folder','shortpixel-image-optimiser');?>">
444
  <p class="settings-info">
445
- <?php _e('Use the Select... button to select site folders. ShortPixel will optimize images and PDFs from the specified folders and their subfolders. In the <a href="upload.php?page=wp-short-pixel-custom">Custom Media list</a>, under the Media menu, you can see the optimization status for each image or PDF in these folders.','shortpixel-image-optimiser');?>
446
  </p>
447
 
448
  <div class="sp-modal-shade sp-folder-picker-shade"></div>
449
  <div class="shortpixel-modal modal-folder-picker shortpixel-hide">
450
- <div class="sp-modal-title"><?php _e('Select the images folder','shortpixel-image-optimiser');?></div>
451
  <div class="sp-folder-picker"></div>
452
- <input type="button" class="button button-info select-folder-cancel" value="<?php _e('Cancel','shortpixel-image-optimiser');?>" style="margin-right: 30px;">
453
- <input type="button" class="button button-primary select-folder" value="<?php _e('Select','shortpixel-image-optimiser');?>">
454
  </div>
455
 
456
  <script>
@@ -462,27 +494,28 @@ use \ShortPixel\Helper\UiHelper as UiHelper;
462
  </td>
463
  </tr>
464
  <tr>
465
- <th scope="row"><label for="authentication"><?php _e('HTTP AUTH credentials','shortpixel-image-optimiser');?></label></th>
466
  <td>
467
  <?php if (! defined('SHORTPIXEL_HTTP_AUTH_USER')): ?>
468
- <input name="siteAuthUser" type="text" id="siteAuthUser" value="<?php echo( stripslashes(esc_html($view->data->siteAuthUser )));?>" class="regular-text" placeholder="<?php _e('User','shortpixel-image-optimiser');?>"><br>
469
- <input name="siteAuthPass" type="text" id="siteAuthPass" value="<?php echo( stripslashes(esc_html($view->data->siteAuthPass )));?>" class="regular-text" placeholder="<?php _e('Password','shortpixel-image-optimiser');?>">
470
  <p class="settings-info">
471
- <?php _e('Only fill in these fields if your site (front-end) is not publicly accessible and visitors need a user/pass to connect to it. If you don\'t know what is this then just <strong>leave the fields empty</strong>.','shortpixel-image-optimiser');?>
472
  </p>
473
  <?php else: ?>
474
- <p><?php _e('The HTTP AUTH credentials have been defined in the wp-config file.', 'shortpixel-image-optimiser'); ?></p>
475
  <?php endif; ?>
476
  </td>
477
  </tr>
478
  </tbody>
479
  </table>
480
  <p class="submit">
481
- <input type="submit" name="save" id="saveAdv" class="button button-primary" title="<?php _e('Save Changes','shortpixel-image-optimiser');?>" value="<?php _e('Save Changes','shortpixel-image-optimiser');?>"> &nbsp;
482
- <input type="submit" name="save_bulk" id="bulkAdvGo" class="button button-primary" title="<?php _e('Save and go to the Bulk Processing page','shortpixel-image-optimiser');?>" value="<?php _e('Save and Go to Bulk Process','shortpixel-image-optimiser');?>"> &nbsp;
483
  </p>
484
  </div>
485
  <script>
 
486
  jQuery(document).ready(function () { ShortPixel.setupAdvancedTab();});
487
  </script>
488
  </section>
3
  use \ShortPixel\Helper\UiHelper as UiHelper;
4
 
5
  ?>
6
+ <section id="tab-adv-settings" class="clearfix <?php echo esc_attr(($this->display_part == 'adv-settings') ? ' sel-tab ' :''); ?> ">
7
+ <h2><a class='tab-link' href='javascript:void(0);' data-id="tab-adv-settings"><?php esc_html_e('Advanced','shortpixel-image-optimiser');?></a></h2>
 
 
8
 
9
  <?php
10
  $deliverWebpAlteredDisabled = '';
27
  } else {
28
  $deliverWebpUnalteredLabel = __('It looks like your .htaccess file cannot be written. Please fix this and then return to refresh this page to enable this option.','shortpixel-image-optimiser');
29
  }
30
+ } elseif (isset($_SERVER['HTTP_USER_AGENT']) && strpos( wp_unslash($_SERVER['HTTP_USER_AGENT']), 'Chrome') !== false) {
31
  // Show a message about the risks and caveats of serving WEBP images via .htaccess
32
+ $deliverWebpUnalteredLabel = '<span style="color: initial;">'. esc_html__('Based on testing your particular hosting configuration, we determined that your server','shortpixel-image-optimiser').
33
+ '&nbsp;<img alt="can or can not" src="'. esc_url(plugins_url( 'res/img/test.jpg' , SHORTPIXEL_PLUGIN_FILE)) .'">&nbsp;'.
34
+ esc_html__('serve the WebP or AVIF versions of the JPEG files seamlessly, via .htaccess.','shortpixel-image-optimiser').' <a href="https://shortpixel.com/knowledge-base/article/127-delivering-webp-images-via-htaccess" target="_blank" data-beacon-article="5c1d050e04286304a71d9ce4">Open article to read more about this.</a></span>';
35
  }
36
  }
37
 
51
  <table class="form-table">
52
  <tbody>
53
  <tr>
54
+ <th scope="row"><?php esc_html_e('Next Generation Images','shortpixel-image-optimiser');?></th>
55
  <td>
56
  <div class='switch_button'>
57
  <div class="spio-inline-help"><span class="dashicons dashicons-editor-help" title="Click for more info" data-link="https://shortpixel.com/knowledge-base/article/286-how-to-serve-webp-files-using-spio"></span></div>
58
  <label>
59
  <input type="checkbox" class="switch" name="createWebp" value="1" <?php checked( $view->data->createWebp, "1" );?>>
60
  <div class="the_switch">&nbsp; </div>
61
+ <?php printf(esc_html__('Create %s WebP versions %s of the images, with the additional cost of 1 credit = 1 image or thumbnail.','shortpixel-image-optimiser'), '<a href="https://shortpixel.com/blog/how-webp-images-can-speed-up-your-site/" target="_blank">', '</a>' );?>
62
  </label>
63
  </div>
64
 
69
  <label>
70
  <input type="checkbox" class="switch" name="createAvif" value="1" <?php checked( $view->data->createAvif, "1" );?>>
71
  <div class="the_switch">&nbsp; </div>
72
+ <?php printf(esc_html__('Create %s AVIF versions %s of the images, with the additional cost of 1 credit = 1 image or thumbnail.','shortpixel-image-optimiser'), '<a href="https://shortpixel.com/blog/what-is-avif-and-why-is-it-good/" target="_blank">', '</a>');?>
73
  </label>
74
  </div>
75
 
76
 
77
  <?php if($deliverAVIFLabel || true){ ?>
78
  <p class="sp-notice">
79
+ <?php echo ( $deliverAVIFLabel );?>
80
  </p>
81
  <?php } ?>
82
 
88
  <label>
89
  <input type="checkbox" class="switch" name="deliverWebp" data-toggle="deliverTypes" value="1" <?php checked( ($view->data->deliverWebp > 0), true);?>>
90
  <div class="the_switch">&nbsp; </div>
91
+ <?php esc_html_e('Deliver the next generation versions of the images in the front-end:','shortpixel-image-optimiser');?>
92
  </label>
93
  </div>
94
 
95
 
96
  <ul class="deliverWebpTypes toggleTarget" id="deliverTypes">
97
  <li>
98
+ <input type="radio" name="deliverWebpType" id="deliverWebpAltered" <?php checked( ($view->data->deliverWebp >= 1 && $view->data->deliverWebp <= 2), true); ?> <?php echo esc_attr( $deliverWebpAlteredDisabled );?> value="deliverWebpAltered" data-toggle="deliverAlteringTypes">
99
  <label for="deliverWebpAltered">
100
+ <?php esc_html_e('Using the &lt;PICTURE&gt; tag syntax','shortpixel-image-optimiser');?>
101
  </label>
102
 
103
  <?php if($deliverWebpAlteredDisabledNotice){ ?>
104
  <p class="sp-notice">
105
+ <?php esc_html_e('After the option to work on .htaccess was selected, the .htaccess file has become unaccessible / read-only. Please make the .htaccess file writeable again to be able to further set this option up.','shortpixel-image-optimiser')?>
106
  </p>
107
  <?php } ?>
108
 
109
  <p class="settings-info">
110
+ <?php esc_html_e('Each &lt;img&gt; will be replaced with a &lt;picture&gt; tag that will also provide AVIF and WebP images for browsers that support it. Also, it loads the picturefill.js for browsers that don\'t support the &lt;picture&gt; tag. You don\'t need to activate this if you\'re using the Cache Enabler plugin because your AVIF\WebP images are already handled by this plugin. <strong>Please run some tests before using this option!</strong> If the styles that your theme is using rely on the position of your &lt;img&gt; tags, you may experience display problems.','shortpixel-image-optimiser'); ?>
111
+ <strong><?php esc_html_e('You can revert anytime to the previous state just by deactivating the option.','shortpixel-image-optimiser'); ?></strong>
112
  </p>
113
 
114
  <ul class="deliverWebpAlteringTypes toggleTarget" id="deliverAlteringTypes">
115
  <li>
116
  <input type="radio" name="deliverWebpAlteringType" id="deliverWebpAlteredWP" <?php checked(($view->data->deliverWebp == 2), true);?> value="deliverWebpAlteredWP">
117
  <label for="deliverWebpAlteredWP">
118
+ <?php esc_html_e('Only via Wordpress hooks (like the_content, the_excerpt, etc)');?>
119
  </label>
120
  </li>
121
  <li>
122
  <input type="radio" name="deliverWebpAlteringType" id="deliverWebpAlteredGlobal" <?php checked(($view->data->deliverWebp == 1),true)?> value="deliverWebpAlteredGlobal">
123
  <label for="deliverWebpAlteredGlobal">
124
+ <?php esc_html_e('Global (processes the whole output buffer before sending the HTML to the browser)','shortpixel-image-optimiser');?>
125
  </label>
126
  </li>
127
  </ul>
128
  </li>
129
  <li>
130
+ <input type="radio" name="deliverWebpType" id="deliverWebpUnaltered" <?php checked(($view->data->deliverWebp == 3), true);?> <?php echo esc_attr( $deliverWebpUnalteredDisabled );?> value="deliverWebpUnaltered" data-toggle="deliverAlteringTypes" data-toggle-reverse>
131
 
132
  <label for="deliverWebpUnaltered">
133
+ <?php esc_html_e('Without altering the page code (via .htaccess)','shortpixel-image-optimiser')?>
134
  </label>
135
  <?php if($deliverWebpUnalteredLabel){ ?>
136
  <p class="sp-notice"><strong>
144
  </td>
145
  </tr>
146
  <tr>
147
+ <th scope="row"><?php esc_html_e('Optimize media on upload','shortpixel-image-optimiser');?></th>
148
  <td>
149
 
150
  <div class='switch_button'>
152
  <label>
153
  <input type="checkbox" class="switch" name="autoMediaLibrary" id='autoMediaLibrary' value="1" <?php checked( $view->data->autoMediaLibrary, "1" );?>>
154
  <div class="the_switch">&nbsp; </div>
155
+ <?php esc_html_e('Automatically optimize images after they are uploaded (recommended).','shortpixel-image-optimiser');?>
156
  </label>
157
  </div>
158
  </td>
164
 
165
 
166
  <tr id="frontBootstrapRow">
167
+ <th scope="row"><?php esc_html_e('Process in the front-end','shortpixel-image-optimiser');?></th>
168
  <td>
169
  <input name="frontBootstrap" type="checkbox" id="frontBootstrap" value="1" <?php checked( $view->data->frontBootstrap, '1' );?>>
170
+ <label for="frontBootstrap"><?php esc_html_e('Automatically optimize images added by users in front-end of the site.','shortpixel-image-optimiser');?></label>
171
 
172
  </td>
173
  </tr>
175
  <th scope='row'>&nbsp;</th>
176
  <td>
177
  <div class="spio-inline-help"><span class="dashicons dashicons-editor-help" title="Click for more info" data-link="https://shortpixel.helpscoutdocs.com/article/536-why-is-the-option-process-in-the-front-end-gone"></span></div>
178
+ <div class='view-notice warning'><p><?php esc_html_e('Important. From version 5 the front processing option is no longer available. There will be no processing on the frontend. To enable optimizing images without visiting the backend, please see the options available for command line optimization.', 'shortpixel-image-optimiser') ?></p>
179
+ <p><?php esc_html_e('To turn off this message, click the checkbox and save settings', 'shortpixel-image-optimiser'); ?></p>
180
  </div>
181
  </td>
182
  </tr>
187
 
188
  <?php if($this->has_nextgen) { ?>
189
  <tr>
190
+ <th scope="row"><?php esc_html_e('NextGen','shortpixel-image-optimiser');?></th>
191
  <td>
192
  <div class='switch_button'>
193
  <label>
194
  <input name="includeNextGen" type="checkbox" id="nextGen" value='1' <?php echo checked($view->data->includeNextGen,'1' );?>>
195
 
196
  <div class="the_switch">&nbsp; </div>
197
+ <?php esc_html_e('Optimize NextGen galleries.','shortpixel-image-optimiser');?>
198
  </label>
199
  </div>
200
 
202
  </tr>
203
  <?php } ?>
204
  <tr>
205
+ <th scope="row"><?php esc_html_e('Optimize PDFs','shortpixel-image-optimiser');?></th>
206
  <td>
207
  <div class='switch_button'>
208
  <div class="spio-inline-help"><span class="dashicons dashicons-editor-help" title="Click for more info" data-link="https://shortpixel.com/knowledge-base/article/520-settings-optimize-pdfs"></span></div>
210
  <label>
211
  <input type="checkbox" class="switch" name="optimizePdfs" value="1" <?php checked( $view->data->optimizePdfs, "1" );?>>
212
  <div class="the_switch">&nbsp; </div>
213
+ <?php esc_html_e('Also optimize PDF documents.','shortpixel-image-optimiser');?>
214
  </label>
215
  </div>
216
 
217
  </td>
218
  </tr>
219
  <tr>
220
+ <th scope="row"><?php esc_html_e('Optimize Retina images','shortpixel-image-optimiser');?></th>
221
  <td>
222
  <div class='switch_button'>
223
  <div class="spio-inline-help"><span class="dashicons dashicons-editor-help" title="Click for more info" data-link="https://shortpixel.com/knowledge-base/article/518-settings-optimize-retina-images"></span></div>
224
  <label>
225
  <input type="checkbox" class="switch" name="optimizeRetina" value="1" <?php checked( $view->data->optimizeRetina, "1" );?>>
226
  <div class="the_switch">&nbsp; </div>
227
+ <?php esc_html_e('Also optimize the Retina images (@2x) if they exist.','shortpixel-image-optimiser');?>
228
  </label>
229
  </div>
230
  </td>
231
  </tr>
232
  <tr>
233
+ <th scope="row"><?php esc_html_e('Optimize other thumbnails','shortpixel-image-optimiser');?></th>
234
  <td>
235
 
236
 
239
  <label>
240
  <input type="checkbox" class="switch" name="optimizeUnlisted" value="1" <?php checked( $view->data->optimizeUnlisted, "1" );?>>
241
  <div class="the_switch">&nbsp; </div>
242
+ <?php esc_html_e('Also optimize unlisted thumbnails, if found.','shortpixel-image-optimiser');?>
243
  </label>
244
  </div>
245
  </td>
246
  </tr>
247
  <tr>
248
+ <th scope="row"><?php esc_html_e('Convert PNG images to JPEG','shortpixel-image-optimiser');?></th>
249
  <td>
250
  <div class='switch_button option-png2jpg'>
251
  <div class="spio-inline-help"><span class="dashicons dashicons-editor-help" title="Click for more info" data-link="https://shortpixel.com/knowledge-base/article/516-settings-convert-png-images-to-jpeg"></span></div>
252
  <label>
253
  <input type="checkbox" class="switch" name="png2jpg" value="1" <?php checked( ($view->data->png2jpg > 0), true);?> <?php echo($this->is_gd_installed ? '' : 'disabled') ?> data-toggle="png2jpgforce">
254
  <div class="the_switch">&nbsp; </div>
255
+ <?php esc_html_e('Automatically convert the PNG images to JPEG, if possible.','shortpixel-image-optimiser'); ?>
256
  </label>
257
  </div>
258
 
259
+ <?php if(!$this->is_gd_installed):
260
+ ?>
261
+ <div style="color:red;"><?php esc_html__('You need PHP GD with support for JPEG and PNG files for this feature. Please ask your hosting provider to install it.','shortpixel-image-optimiser'); ?>
262
+ </div>
263
+ <?php endif; ?>
264
 
265
 
266
  <div class='switch_button option-png2jpgforce toggleTarget suboption' id="png2jpgforce">
268
  <label>
269
  <input type="checkbox" class="switch" name="png2jpgForce" value="1" <?php checked(($view->data->png2jpg > 1), true);?> <?php echo($this->is_gd_installed ? '' : 'disabled') ?>>
270
  <div class="the_switch">&nbsp; </div>
271
+ <?php esc_html_e('Also force the conversion of images with transparency.','shortpixel-image-optimiser'); ?>
272
  </label>
273
  </div>
274
 
277
  <tr class='exif_warning view-notice-row'>
278
  <th scope="row">&nbsp;</th>
279
  <td>
280
+ <div class='view-notice warning'><p><?php printf(esc_html__('Warning - Converting from PNG to JPG will %s not %s keep the EXIF information!', 'shortpixel-image-optimiser'), "<strong>","</strong>"); ?></p></div>
281
  </td>
282
  </tr>
283
  <tr>
284
+ <th scope="row"><?php esc_html_e('CMYK to RGB conversion','shortpixel-image-optimiser');?></th>
285
  <td>
286
  <div class='switch_button'>
287
  <div class="spio-inline-help"><span class="dashicons dashicons-editor-help" title="Click for more info" data-link="https://shortpixel.com/knowledge-base/article/517-settings---cmyk-to-rgb-conversion"></span></div>
288
  <label>
289
  <input type="checkbox" class="switch" name="cmyk2rgb" value="1" <?php checked( $view->data->CMYKtoRGBconversion, "1" );?>>
290
  <div class="the_switch">&nbsp; </div>
291
+ <?php esc_html_e('Adjust your images\' colors for computer and mobile displays.','shortpixel-image-optimiser');?>
292
  </label>
293
  </div>
294
 
295
  </td>
296
  </tr>
297
  <tr>
298
+ <th scope="row"><label for="excludeSizes"><?php esc_html_e('Exclude thumbnail sizes','shortpixel-image-optimiser');?></label></th>
299
  <td>
300
  <div class="option-content">
301
  <div class="spio-inline-help"><span class="dashicons dashicons-editor-help" title="Click for more info" data-link="https://shortpixel.com/knowledge-base/article/113-how-can-i-optimize-only-certain-thumbnail-sizes"></span></div>
305
  <span style="margin-right: 20px;white-space:nowrap">
306
  <label>
307
 
308
+ <input name="excludeSizes[]" type="checkbox" id="excludeSizes_<?php echo esc_attr($sizeKey);?>" <?php
309
+ // @TODO This is unreadable
310
+ echo esc_attr((in_array($sizeKey, $view->data->excludeSizes) ? 'checked' : ''));?>
311
+ value="<?php echo esc_attr($sizeKey);?>">&nbsp;<?php $w=$sizeVal['width']?$sizeVal['width'].'px':'*';$h=$sizeVal['height']?$sizeVal['height'].'px':'*';echo("$sizeKey ({$w} &times; {$h})");?>&nbsp;&nbsp;
312
  </label>
313
  </span><br>
314
  <?php } ?>
316
  </td>
317
  </tr>
318
  <tr>
319
+ <th scope="row"><label for="excludePatterns"><?php esc_html_e('Exclude patterns','shortpixel-image-optimiser');?></label></th>
320
  <td>
321
  <div class="option-content">
322
  <div class="spio-inline-help"><span class="dashicons dashicons-editor-help" title="Click for more info" data-link="https://shortpixel.com/knowledge-base/article/88-how-to-exclude-images-from-being-optimized"></span></div>
323
 
324
  <textarea name="excludePatterns" type="text" id="excludePatterns" placeholder="<?php
325
+ esc_html_e('name:keepbig, path:/full/path/to/exclude/, regex-name:/valid_regex/, size:1000x2000','shortpixel-image-optimiser');?>" rows="4" cols="60"><?php echo esc_html( $excludePatterns );?></textarea>
326
 
327
  </div>
328
  <p class="settings-info">
329
+ <?php
330
+ // Hear you like strong, so I put some strong in your strong.
331
+ printf(esc_html__('Add patterns separated by comma. A pattern consist of a %stype:value%s pair; the accepted types are
332
+ %s"name"%s, %s"path"%s, %s"size"%s, %s"regex-name"%s and %s"regex-path"%s.
333
+ A file is excluded if it matches any of the patterns. %s
334
+
335
+ %s For a %s"name"%s pattern only the filename is matched, for %s"path"%s,
336
  the whole path will be matched (useful for excluding certain (sub)-directories altoghether).
337
+ %s %s
338
+ %s"regex-path"%s and %s"regex-name"%s work the same, except it requires a valid regular expression, contained between slashes. Special characters should be escaped by adding \ in front of them.
339
+ %s %s
340
+
341
+ For the %s"size"%s type, which applies only to Media Library images, %sthe main images (not thumbnails)%s that have the size in the specified range are excluded.
342
+ The format for the "size" exclude is: %sminWidth%s- %smaxWidth%sx%sminHeight%s%s>maxHeight%s, for example %ssize:1000-1100x2000-2200%s. You can also specify a precise size, such as %s1000x2000%s.','shortpixel-image-optimiser'),
343
+ '<strong>', '</strong>',
344
+ '<strong>', '</strong>',
345
+ '<strong>', '</strong>',
346
+ '<strong>', '</strong>',
347
+ '<strong>', '</strong>',
348
+ '<strong>', '</strong>',
349
+ '<br>',
350
+ '<br>',
351
+ '<strong>', '</strong>',
352
+ '<strong>', '</strong>',
353
+ '<strong>', '</strong>',
354
+ '<strong>', '</strong>',
355
+ '<br>',
356
+ '<br>',
357
+ '<strong>', '</strong>',
358
+ '<strong>', '</strong>',
359
+ '<br>',
360
+ '<br>',
361
+ '<strong>', '</strong>',
362
+ '<strong>', '</strong>',
363
+ '<strong>', '</strong>',
364
+ '<strong>', '</strong>',
365
+ '<strong>', '</strong>',
366
+ '<strong>', '</strong>',
367
+ '<strong>', '</strong>',
368
+ '<strong>', '</strong>',
369
+ );?>
370
  </p>
371
  </td>
372
  </tr>
373
  <tr>
374
+ <th scope="row"><label for="additional-media"><?php esc_html_e('Custom media folders','shortpixel-image-optimiser');?></label></th>
375
  <td>
376
+
377
  <?php if($view->customFolders) { ?>
378
 
379
  <div class="option-content">
380
  <div class="spio-inline-help"><span class="dashicons dashicons-editor-help" title="Click for more info" data-link="https://shortpixel.com/knowledge-base/article/46-how-to-optimize-images-in-wordpress-themes-and-plugins"></span></div>
381
  <div class="shortpixel-folders-list">
382
  <div class='heading'>
383
+ <span><?php esc_html_e('Folder name','shortpixel-image-optimiser');?></span>
384
+ <span><?php esc_html_e('Type &amp; Status','shortpixel-image-optimiser');?></span>
385
+ <span><?php esc_html_e('Files','shortpixel-image-optimiser');?></span>
386
+ <span><?php esc_html_e('Last change','shortpixel-image-optimiser');?></span>
387
  <span>&nbsp;</span>
388
  <span class='action'>&nbsp;</span>
389
  </div>
394
 
395
 
396
  $type_display = ($dirObj->get('is_nextgen') ) ? __('Nextgen', 'shortpixel-image-optimiser') . "<br>" : "";
 
397
  $stat = $dirObj->getStats();
398
 
399
+ $fullstatus = esc_html__("Optimized",'shortpixel-image-optimiser') . ": " . $stat->Optimized . ", "
400
+ . " " . esc_html__("Waiting",'shortpixel-image-optimiser') . ": " . $stat->Waiting . ""
401
  ;
402
 
403
  if ($stat->Total == 0)
419
  }
420
 
421
  $action = __("Stop monitoring",'shortpixel-image-optimiser');
422
+
423
  $err = ''; // unused since failed is gone.
424
  if (! $dirObj->exists() && ! $err)
425
  $err = __('Directory does not exist', 'shortpixel-image-optimiser');
432
  $refreshUrl = add_query_arg(array('sp-action' => 'action_refreshfolder', 'folder_id' => $folder_id, 'part' => 'adv-settings'), $this->url); // has url
433
  ?>
434
  <div>
435
+ <span class='folder folder-<?php echo esc_attr($dirObj->get('id')) ?>'><?php echo esc_html($dirObj->getPath()); ?></span>
436
  <span>
437
  <?php if(!($stat->Total == 0)) { ?>
438
+ <span title="<?php echo esc_attr($fullstatus); ?>" class='info-icon'>
439
+ <img alt='<?php esc_html_e('Info Icon', 'shortpixel-image-optimiser') ?>' src='<?php echo esc_url( wpSPIO()->plugin_url('res/img/info-icon.png' ));?>' style="margin-bottom: -2px;"/>
440
  </span>&nbsp;<?php }
441
+ echo esc_html($type_display. ' ' . $optimize_status . $err);
442
  ?>
443
  </span>
444
  <span>
445
+ <?php echo esc_html($stat->Total); ?> files
446
  </span>
447
  <span>
448
+ <?php echo esc_html(UiHelper::formatTS($dirObj->get('updated'))) ?>
449
  </span>
450
  <span>
451
+ <a href='<?php echo esc_url($refreshUrl) ?>' title="<?php esc_html_e('Recheck for new images', 'shortpixel-image-optimiser'); ?>" class='refresh-folder'><i class='dashicons dashicons-update'>&nbsp;</i></a>
452
  </span>
453
  <span class='action'>
454
  <?php if ($action): ?>
455
+ <input type="button" class="button remove-folder-button" data-value="<?php echo esc_attr($dirObj->get('id')); ?>" data-name="<?php echo esc_attr($dirObj->getPath()) ?>" title="<?php echo esc_attr($action . " " . $dirObj->getPath()); ?>" value="<?php echo esc_attr($action); ?>">
456
  <?php endif; ?>
457
  </span>
458
  </div>
464
  <div class='addCustomFolder'>
465
 
466
  <input type="hidden" name="removeFolder" id="removeFolder"/>
467
+ <p class='add-folder-text'><strong><?php esc_html_e('Add a custom folder', 'shortpixel-image-optimiser'); ?></strong></p>
468
  <input type="text" name="addCustomFolderView" id="addCustomFolderView" class="regular-text" value="" disabled style="">&nbsp;
469
  <input type="hidden" name="addCustomFolder" id="addCustomFolder" value=""/>
470
+ <input type="hidden" id="customFolderBase" value="<?php echo esc_attr($this->view->customFolderBase); ?>">
471
 
472
+ <a class="button select-folder-button" title="<?php esc_html_e('Select the images folder on your server.','shortpixel-image-optimiser');?>" href="javascript:void(0);">
473
+ <?php esc_html_e('Select','shortpixel-image-optimiser');?>
474
  </a>
475
+ <input type="submit" name="save" id="saveAdvAddFolder" class="button button-primary hidden" title="<?php esc_html_e('Add this Folder','shortpixel-image-optimiser');?>" value="<?php esc_html_e('Add this Folder','shortpixel-image-optimiser');?>">
476
  <p class="settings-info">
477
+ <?php printf(esc_html__('Use the Select... button to select site folders. ShortPixel will optimize images and PDFs from the specified folders and their subfolders. In the %s Custom Media list %s, under the Media menu, you can see the optimization status for each image or PDF in these folders.','shortpixel-image-optimiser'), '<a href="upload.php?page=wp-short-pixel-custom">', '</a>');?>
478
  </p>
479
 
480
  <div class="sp-modal-shade sp-folder-picker-shade"></div>
481
  <div class="shortpixel-modal modal-folder-picker shortpixel-hide">
482
+ <div class="sp-modal-title"><?php esc_html_e('Select the images folder','shortpixel-image-optimiser');?></div>
483
  <div class="sp-folder-picker"></div>
484
+ <input type="button" class="button button-info select-folder-cancel" value="<?php esc_html_e('Cancel','shortpixel-image-optimiser');?>" style="margin-right: 30px;">
485
+ <input type="button" class="button button-primary select-folder" value="<?php esc_html_e('Select','shortpixel-image-optimiser');?>">
486
  </div>
487
 
488
  <script>
494
  </td>
495
  </tr>
496
  <tr>
497
+ <th scope="row"><label for="authentication"><?php esc_html_e('HTTP AUTH credentials','shortpixel-image-optimiser');?></label></th>
498
  <td>
499
  <?php if (! defined('SHORTPIXEL_HTTP_AUTH_USER')): ?>
500
+ <input name="siteAuthUser" type="text" id="siteAuthUser" value="<?php echo( esc_html(wp_unslash($view->data->siteAuthUser )));?>" class="regular-text" placeholder="<?php esc_html_e('User','shortpixel-image-optimiser');?>"><br>
501
+ <input name="siteAuthPass" type="text" id="siteAuthPass" value="<?php echo( esc_html(wp_unslash($view->data->siteAuthPass )));?>" class="regular-text" placeholder="<?php esc_html_e('Password','shortpixel-image-optimiser');?>">
502
  <p class="settings-info">
503
+ <?php esc_html_e('Only fill in these fields if your site (front-end) is not publicly accessible and visitors need a user/pass to connect to it. If you don\'t know what is this then just <strong>leave the fields empty</strong>.','shortpixel-image-optimiser');?>
504
  </p>
505
  <?php else: ?>
506
+ <p><?php esc_html_e('The HTTP AUTH credentials have been defined in the wp-config file.', 'shortpixel-image-optimiser'); ?></p>
507
  <?php endif; ?>
508
  </td>
509
  </tr>
510
  </tbody>
511
  </table>
512
  <p class="submit">
513
+ <input type="submit" name="save" id="saveAdv" class="button button-primary" title="<?php esc_attr_e('Save Changes','shortpixel-image-optimiser');?>" value="<?php esc_attr_e('Save Changes','shortpixel-image-optimiser');?>"> &nbsp;
514
+ <input type="submit" name="save_bulk" id="bulkAdvGo" class="button button-primary" title="<?php esc_attr_e('Save and go to the Bulk Processing page','shortpixel-image-optimiser');?>" value="<?php esc_attr_e('Save and Go to Bulk Process','shortpixel-image-optimiser');?>"> &nbsp;
515
  </p>
516
  </div>
517
  <script>
518
+ <!-- @todo // Inline JS -->
519
  jQuery(document).ready(function () { ShortPixel.setupAdvancedTab();});
520
  </script>
521
  </section>
class/view/settings/part-cloudflare.php CHANGED
@@ -3,32 +3,33 @@ namespace ShortPixel;
3
 
4
  ?>
5
 
6
- <section id="tab-cloudflare" <?php echo ($this->display_part == 'cloudflare') ? ' class="sel-tab" ' :''; ?>>
7
  <h2><a class='tab-link' href='javascript:void(0);'
8
- data-id="tab-cloudflare"><?php _e('Cloudflare API', 'shortpixel-image-optimiser'); ?></a>
9
  </h2>
10
 
11
  <div class="wp-shortpixel-tab-content" style="visibility: hidden">
12
  <?php
13
 
14
  if(! $this->is_curl_installed) {
15
- echo('<p style="font-weight:bold;color:red">' . __("Please enable PHP cURL extension for the Cloudflare integration to work.", 'shortpixel-image-optimiser') . '</p>' );
16
  }
17
  ?>
18
  <div class="spio-inline-help"><span class="dashicons dashicons-editor-help" title="Click for more info" data-link="https://shortpixel.com/knowledge-base/article/160-cloudlfare"></span></div>
19
- <p><?php _e("If you are using Cloudflare on your site, we recommend that you to fill in the details below. This will allow ShortPixel to work seamlessly with Cloudflare, so that any image optimized/restored by ShortPixel is automatically updated on Cloudflare as well.",'shortpixel-image-optimiser');?></p>
 
20
 
21
  <table class="form-table">
22
  <tbody>
23
  <tr>
24
  <th scope="row"><label
25
- for="cloudflare-zone-id"><?php _e('Zone ID', 'shortpixel-image-optimiser'); ?></label>
26
  </th>
27
  <td>
28
  <input name="cloudflareZoneID" type="text" id="cloudflare-zone-id" <?php echo(! $this->is_curl_installed ? 'disabled' : '');?>
29
- value="<?php echo(stripslashes(esc_html($view->data->cloudflareZoneID))); ?>" class="regular-text">
30
  <p class="settings-info">
31
- <?php _e('You can find this in your Cloudflare account in the "Overview" section for your domain.','shortpixel-image-optimiser');?>
32
  </p>
33
  </td>
34
  </tr>
@@ -44,43 +45,43 @@ namespace ShortPixel;
44
 
45
 
46
  ?>
47
- <label><input type='radio' name='cf_auth_switch' value='token' <?php echo $token_checked ?> ><span><?php _e('Cloudflare Token', 'shortpixel-image-optimiser'); ?></span></label>
48
  <?php if ($view->hide_cf_global === false): ?>
49
- <label><input type='radio' name='cf_auth_switch' value='global' <?php echo $global_checked ?> ><span><?php _e('Global API Key', 'shortpixel-image-optimiser') ?></span></label>
50
  <?php endif; ?>
51
  </th>
52
  <td class='token-cell'>
53
- <input name="cloudflareToken" type="text" id="cloudflare-token" <?php echo(! $this->is_curl_installed ? 'disabled' : '');?> value="<?php echo $view->data->cloudflareToken ?>" class='regular-text' autocomplete="off">
54
 
55
  <?php if ($view->hide_cf_global === false): ?>
56
- <p class='settings-info'><?php printf(__('%s Preferred Method %s. Enter your %s site token %s for authentication. This token needs %sCache Purge permission!%s', 'shortpixel-image-optimiser'), '<b>', '</b>', '<a href="https://dash.cloudflare.com/profile/api-tokens" target="_blank">', '</a>', '<a href="https://shortpixel.com/knowledge-base/article/325-using-shortpixel-image-optimizer-with-cloudflare-api-token" target="_blank">', '</a>'); ?></p>
57
- <p class='settings-info'><?php _e('When using a token, leave the email and global API key fields empty.', 'shortpixel-image-optimiser'); ?></p>
58
  <?php else: ?>
59
- <p class='settings-info'><?php printf(__('Enter your %s site token %s for authentication. This token needs %s Cache Purge permission %s! ', 'shortpixel-image-optimiser'), '<a href="https://dash.cloudflare.com/profile/api-tokens" target="_blank">', '</a>', '<a href="https://shortpixel.com/knowledge-base/article/325-using-shortpixel-image-optimizer-with-cloudflare-api-token" target="_blank">', '</a>'); ?></p>
60
  <?php endif; ?>
61
  <a href="https://shortpixel.com/knowledge-base/article/325-using-shortpixel-image-optimizer-with-cloudflare-api-token/" target="_blank" class="shortpixel-help-link">
62
- <span class="dashicons dashicons-editor-help"></span><?php _e('How to set it up','shortpixel-image-optimiser');?>
63
  </a>
64
 
65
  </td>
66
  <?php if ($view->hide_cf_global === false): ?>
67
  <td class='authkey-cell'>
68
- <input name="cloudflareAuthKey" type="text" id="cloudflare-auth-key" <?php echo(! $this->is_curl_installed ? 'disabled' : '');?> value="<?php echo(stripslashes(esc_html($view->data->cloudflareAuthKey))); ?>" class="regular-text" autocomplete="off">
69
  <p class="settings-info">
70
- <?php _e("This can be found when you're logged into your account, on the My Profile page:",'shortpixel-image-optimiser');?> <a href='https://www.cloudflare.com/a/profile' target='_blank'>https://www.cloudflare.com/a/profile</a>
71
  </p>
72
  </td>
73
  <?php endif; ?>
74
  </tr>
75
  <tr class='email-cell'>
76
  <th scope="row">
77
- <label for="cloudflare-email"><?php _e('Cloudflare E-mail:', 'shortpixel-image-optimiser'); ?></label>
78
  </th>
79
  <td>
80
  <input name="cloudflareEmail" type="text" id="cloudflare-email" <?php echo(! $this->is_curl_installed ? 'disabled' : '');?>
81
- value="<?php echo( stripslashes(esc_html($view->data->cloudflareEmail))); ?>" class="regular-text">
82
  <p class="settings-info">
83
- <?php _e('The e-mail address you use to login to CloudFlare.','shortpixel-image-optimiser');?>
84
  </p>
85
  </td>
86
  </tr>
@@ -89,12 +90,12 @@ namespace ShortPixel;
89
  </table>
90
  <p class="submit">
91
  <input type="submit" name="saveCloudflare" id="saveCloudflare" class="button button-primary"
92
- title="<?php _e('Save Changes', 'shortpixel-image-optimiser'); ?>"
93
- value="<?php _e('Save Changes', 'shortpixel-image-optimiser'); ?>"> &nbsp;
94
  </p>
95
  </div>
96
  <script language="javascript">
97
-
98
  function switchCF()
99
  {
100
  if ( jQuery('input[name="cf_auth_switch"]:checked').val() == 'token')
3
 
4
  ?>
5
 
6
+ <section id="tab-cloudflare" class="<?php echo esc_attr(($this->display_part == 'cloudflare') ? 'sel-tab ' :''); ?>">
7
  <h2><a class='tab-link' href='javascript:void(0);'
8
+ data-id="tab-cloudflare"><?php esc_html_e('Cloudflare API', 'shortpixel-image-optimiser'); ?></a>
9
  </h2>
10
 
11
  <div class="wp-shortpixel-tab-content" style="visibility: hidden">
12
  <?php
13
 
14
  if(! $this->is_curl_installed) {
15
+ echo('<p style="font-weight:bold;color:red">' . esc_html__("Please enable PHP cURL extension for the Cloudflare integration to work.", 'shortpixel-image-optimiser') . '</p>' );
16
  }
17
  ?>
18
  <div class="spio-inline-help"><span class="dashicons dashicons-editor-help" title="Click for more info" data-link="https://shortpixel.com/knowledge-base/article/160-cloudlfare"></span></div>
19
+
20
+ <p><?php esc_html_e("If you are using Cloudflare on your site, we recommend that you to fill in the details below. This will allow ShortPixel to work seamlessly with Cloudflare, so that any image optimized/restored by ShortPixel is automatically updated on Cloudflare as well.",'shortpixel-image-optimiser');?></p>
21
 
22
  <table class="form-table">
23
  <tbody>
24
  <tr>
25
  <th scope="row"><label
26
+ for="cloudflare-zone-id"><?php esc_html_e('Zone ID', 'shortpixel-image-optimiser'); ?></label>
27
  </th>
28
  <td>
29
  <input name="cloudflareZoneID" type="text" id="cloudflare-zone-id" <?php echo(! $this->is_curl_installed ? 'disabled' : '');?>
30
+ value="<?php echo( esc_attr(wp_unslash($view->data->cloudflareZoneID))); ?>" class="regular-text">
31
  <p class="settings-info">
32
+ <?php esc_html_e('You can find this in your Cloudflare account in the "Overview" section for your domain.','shortpixel-image-optimiser');?>
33
  </p>
34
  </td>
35
  </tr>
45
 
46
 
47
  ?>
48
+ <label><input type='radio' name='cf_auth_switch' value='token' <?php echo esc_attr($token_checked) ?> ><span><?php esc_html_e('Cloudflare Token', 'shortpixel-image-optimiser'); ?></span></label>
49
  <?php if ($view->hide_cf_global === false): ?>
50
+ <label><input type='radio' name='cf_auth_switch' value='global' <?php echo esc_attr($global_checked) ?> ><span><?php esc_html_e('Global API Key', 'shortpixel-image-optimiser') ?></span></label>
51
  <?php endif; ?>
52
  </th>
53
  <td class='token-cell'>
54
+ <input name="cloudflareToken" type="text" id="cloudflare-token" <?php echo(! $this->is_curl_installed ? 'disabled' : '');?> value="<?php echo esc_attr($view->data->cloudflareToken) ?>" class='regular-text' autocomplete="off">
55
 
56
  <?php if ($view->hide_cf_global === false): ?>
57
+ <p class='settings-info'><?php printf(esc_html__('%s Preferred Method %s. Enter your %s site token %s for authentication. This token needs %sCache Purge permission!%s', 'shortpixel-image-optimiser'), '<b>', '</b>', '<a href="https://dash.cloudflare.com/profile/api-tokens" target="_blank">', '</a>', '<a href="https://shortpixel.com/knowledge-base/article/325-using-shortpixel-image-optimizer-with-cloudflare-api-token" target="_blank">', '</a>'); ?></p>
58
+ <p class='settings-info'><?php esc_html_e('When using a token, leave the email and global API key fields empty.', 'shortpixel-image-optimiser'); ?></p>
59
  <?php else: ?>
60
+ <p class='settings-info'><?php printf(esc_html__('Enter your %s site token %s for authentication. This token needs %s Cache Purge permission %s! ', 'shortpixel-image-optimiser'), '<a href="https://dash.cloudflare.com/profile/api-tokens" target="_blank">', '</a>', '<a href="https://shortpixel.com/knowledge-base/article/325-using-shortpixel-image-optimizer-with-cloudflare-api-token" target="_blank">', '</a>'); ?></p>
61
  <?php endif; ?>
62
  <a href="https://shortpixel.com/knowledge-base/article/325-using-shortpixel-image-optimizer-with-cloudflare-api-token/" target="_blank" class="shortpixel-help-link">
63
+ <span class="dashicons dashicons-editor-help"></span><?php esc_html_e('How to set it up','shortpixel-image-optimiser');?>
64
  </a>
65
 
66
  </td>
67
  <?php if ($view->hide_cf_global === false): ?>
68
  <td class='authkey-cell'>
69
+ <input name="cloudflareAuthKey" type="text" id="cloudflare-auth-key" <?php echo(! $this->is_curl_installed ? 'disabled' : '');?> value="<?php echo(esc_html(wp_unslash($view->data->cloudflareAuthKey))); ?>" class="regular-text" autocomplete="off">
70
  <p class="settings-info">
71
+ <?php esc_html_e("This can be found when you're logged into your account, on the My Profile page:",'shortpixel-image-optimiser');?> <a href='https://www.cloudflare.com/a/profile' target='_blank'>https://www.cloudflare.com/a/profile</a>
72
  </p>
73
  </td>
74
  <?php endif; ?>
75
  </tr>
76
  <tr class='email-cell'>
77
  <th scope="row">
78
+ <label for="cloudflare-email"><?php esc_html_e('Cloudflare E-mail:', 'shortpixel-image-optimiser'); ?></label>
79
  </th>
80
  <td>
81
  <input name="cloudflareEmail" type="text" id="cloudflare-email" <?php echo(! $this->is_curl_installed ? 'disabled' : '');?>
82
+ value="<?php echo( esc_html(wp_unslash($view->data->cloudflareEmail))); ?>" class="regular-text">
83
  <p class="settings-info">
84
+ <?php esc_html_e('The e-mail address you use to login to CloudFlare.','shortpixel-image-optimiser');?>
85
  </p>
86
  </td>
87
  </tr>
90
  </table>
91
  <p class="submit">
92
  <input type="submit" name="saveCloudflare" id="saveCloudflare" class="button button-primary"
93
+ title="<?php esc_attr_e('Save Changes', 'shortpixel-image-optimiser'); ?>"
94
+ value="<?php esc_attr_e('Save Changes', 'shortpixel-image-optimiser'); ?>"> &nbsp;
95
  </p>
96
  </div>
97
  <script language="javascript">
98
+ <!-- @todo Inline JS - remove version 5.1 -->
99
  function switchCF()
100
  {
101
  if ( jQuery('input[name="cf_auth_switch"]:checked').val() == 'token')
class/view/settings/part-debug.php CHANGED
@@ -14,14 +14,14 @@ $env = \wpSPIO()->env();
14
 
15
  ?>
16
 
17
- <section id="tab-debug" <?php echo ($this->display_part == 'debug') ? ' class="sel-tab" ' :''; ?>>
18
  <h2><a class='tab-link' href='javascript:void(0);' data-id="tab-debug">
19
- <?php _e('Debug','shortpixel-image-optimiser');?></a>
20
  </h2>
21
 
22
  <div class="wp-shortpixel-options wp-shortpixel-tab-content" style="visibility: hidden">
23
  <div class='env'>
24
- <h3><?php _e('Environment', 'shortpixel'); ?></h3>
25
  <div class='flex'>
26
  <span>NGINX</span><span><?php var_export($this->is_nginx); ?></span>
27
  <span>KeyVerified</span><span><?php var_export($this->is_verifiedkey); ?></span>
@@ -37,17 +37,27 @@ $env = \wpSPIO()->env();
37
  <span>GD Installed</span><span><?php var_export($env->is_gd_installed); ?></span>
38
  <span>Curl Installed</span><span><?php var_export($env->is_curl_installed); ?></span>
39
  </div>
 
 
 
 
 
 
 
 
 
 
40
  </div>
41
 
42
  <div class='settings'>
43
- <h3><?php _e('Settings', 'shortpixel'); ?></h3>
44
  <?php $local = $this->view->data;
45
  $local->apiKey = strlen($local->apiKey) . ' chars'; ?>
46
  <pre><?php var_export($local); ?></pre>
47
  </div>
48
 
49
  <div class='quotadata'>
50
- <h3><?php _e('Quota Data', 'shortpixel'); ?></h3>
51
  <pre><?php var_export($this->quotaData); ?></pre>
52
  </div>
53
 
@@ -59,35 +69,35 @@ $env = \wpSPIO()->env();
59
  </form>
60
  </div>
61
  <div class="stats env">
62
- <h3><?php _e('Stats', 'shortpixel-image-optimiser'); ?></h3>
63
  <h4>Media</h4>
64
  <div class='flex'>
65
  <?php $statsControl = StatsController::getInstance();
66
  ?>
67
- <span>Items</span><span><?php echo $statsControl->find('media', 'items'); ?></span>
68
- <span>Thumbs</span><span><?php echo $statsControl->find('media', 'thumbs'); ?></span>
69
- <span>Images</span><span><?php echo $statsControl->find('media', 'images'); ?></span>
70
- <span>ItemsTotal</span><span><?php echo $statsControl->find('media', 'itemsTotal'); ?></span>
71
- <span>ThumbsTotal</span><span><?php echo $statsControl->find('media', 'thumbsTotal'); ?></span>
72
  </div>
73
  <h4>Custom</h4>
74
  <div class='flex'>
75
- <span>Custom Optimized</span><span><?php echo $statsControl->find('custom', 'items'); ?></span>
76
- <span>Custom itemsTotal</span><span><?php echo $statsControl->find('custom', 'itemsTotal'); ?>
77
  </span>
78
  </div>
79
  <h4>Total</h4>
80
  <div class='flex'>
81
- <span>Items</span><span><?php echo $statsControl->find('total', 'items'); ?></span>
82
- <span>Images</span><span><?php echo $statsControl->find('total', 'images'); ?></span>
83
- <span>Thumbs</span><span><?php echo $statsControl->find('total', 'thumbs'); ?></span>
84
  </div>
85
  <h4>Period</h4>
86
  <div class='flex'>
87
- <span>Month #1 </span><span><?php echo $statsControl->find('period', 'months', '1'); ?></span>
88
- <span>Month #2 </span><span><?php echo $statsControl->find('period', 'months', '2'); ?></span>
89
- <span>Month #3 </span><span><?php echo $statsControl->find('period', 'months', '3'); ?></span>
90
- <span>Month #4 </span><span><?php echo $statsControl->find('period', 'months', '4'); ?></span>
91
  </div>
92
  </div> <!-- stats -->
93
 
@@ -102,7 +112,7 @@ $env = \wpSPIO()->env();
102
  $notices = $noticeController->getNotices();
103
  ?>
104
 
105
- <h3>Notices (<?php echo count($notices); ?>)</h3>
106
  <div class='table notices'>
107
 
108
  <div class='head'>
@@ -112,7 +122,7 @@ $env = \wpSPIO()->env();
112
  <?php foreach ($notices as $noticeObj): ?>
113
 
114
  <div>
115
- <span><?php echo $noticeObj->getID(); ?></span>
116
  <span><?php echo ($noticeObj->isDone()) ? 'Y' : 'N'; ?> </span>
117
  <span><?php echo ($noticeObj->isDismissed()) ? 'Y' : 'N'; ?> </span>
118
  <span><?php echo ($noticeObj->isPersistent()) ? 'Y' : 'N'; ?> </span>
@@ -182,7 +192,7 @@ $env = \wpSPIO()->env();
182
  <option>All</option>
183
  <?php foreach($queues as $name => $q)
184
  {
185
- echo "<option>$name</option>";
186
  }
187
  ?>
188
  </select>
14
 
15
  ?>
16
 
17
+ <section id="tab-debug" class="<?php echo esc_attr(($this->display_part == 'debug') ? ' sel-tab ' :''); ?>">
18
  <h2><a class='tab-link' href='javascript:void(0);' data-id="tab-debug">
19
+ <?php esc_html_e('Debug','shortpixel-image-optimiser');?></a>
20
  </h2>
21
 
22
  <div class="wp-shortpixel-options wp-shortpixel-tab-content" style="visibility: hidden">
23
  <div class='env'>
24
+ <h3><?php esc_html_e('Environment', 'shortpixel'); ?></h3>
25
  <div class='flex'>
26
  <span>NGINX</span><span><?php var_export($this->is_nginx); ?></span>
27
  <span>KeyVerified</span><span><?php var_export($this->is_verifiedkey); ?></span>
37
  <span>GD Installed</span><span><?php var_export($env->is_gd_installed); ?></span>
38
  <span>Curl Installed</span><span><?php var_export($env->is_curl_installed); ?></span>
39
  </div>
40
+
41
+ <div class='flex'>
42
+ <span>Uploads Base</span><span><?php echo esc_html((defined('SHORTPIXEL_UPLOADS_BASE')) ? SHORTPIXEL_UPLOADS_BASE : 'not defined'); ?></span>
43
+ <span>Uploads Name</span><span><?php echo esc_html((defined('SHORTPIXEL_UPLOADS_NAME')) ? SHORTPIXEL_UPLOADS_NAME : 'not defined'); ?></span>
44
+ <span>Backup Folder</span><span><?php echo esc_html((defined('SHORTPIXEL_BACKUP_FOLDER')) ? SHORTPIXEL_BACKUP_FOLDER : 'not defined'); ?></span>
45
+ <span>Backup URL</span><span><?php echo esc_html((defined('SHORTPIXEL_BACKUP_URL')) ? SHORTPIXEL_BACKUP_URL : 'not defined'); ?></span>
46
+
47
+
48
+
49
+ </div>
50
  </div>
51
 
52
  <div class='settings'>
53
+ <h3><?php esc_html_e('Settings', 'shortpixel'); ?></h3>
54
  <?php $local = $this->view->data;
55
  $local->apiKey = strlen($local->apiKey) . ' chars'; ?>
56
  <pre><?php var_export($local); ?></pre>
57
  </div>
58
 
59
  <div class='quotadata'>
60
+ <h3><?php esc_html_e('Quota Data', 'shortpixel'); ?></h3>
61
  <pre><?php var_export($this->quotaData); ?></pre>
62
  </div>
63
 
69
  </form>
70
  </div>
71
  <div class="stats env">
72
+ <h3><?php esc_html_e('Stats', 'shortpixel-image-optimiser'); ?></h3>
73
  <h4>Media</h4>
74
  <div class='flex'>
75
  <?php $statsControl = StatsController::getInstance();
76
  ?>
77
+ <span>Items</span><span><?php echo esc_html($statsControl->find('media', 'items')); ?></span>
78
+ <span>Thumbs</span><span><?php echo esc_html($statsControl->find('media', 'thumbs')); ?></span>
79
+ <span>Images</span><span><?php echo esc_html($statsControl->find('media', 'images')); ?></span>
80
+ <span>ItemsTotal</span><span><?php echo esc_html($statsControl->find('media', 'itemsTotal')); ?></span>
81
+ <span>ThumbsTotal</span><span><?php echo esc_html($statsControl->find('media', 'thumbsTotal')); ?></span>
82
  </div>
83
  <h4>Custom</h4>
84
  <div class='flex'>
85
+ <span>Custom Optimized</span><span><?php echo esc_html($statsControl->find('custom', 'items')); ?></span>
86
+ <span>Custom itemsTotal</span><span><?php echo esc_html($statsControl->find('custom', 'itemsTotal')); ?>
87
  </span>
88
  </div>
89
  <h4>Total</h4>
90
  <div class='flex'>
91
+ <span>Items</span><span><?php echo esc_html($statsControl->find('total', 'items')); ?></span>
92
+ <span>Images</span><span><?php echo esc_html($statsControl->find('total', 'images')); ?></span>
93
+ <span>Thumbs</span><span><?php echo esc_html($statsControl->find('total', 'thumbs')); ?></span>
94
  </div>
95
  <h4>Period</h4>
96
  <div class='flex'>
97
+ <span>Month #1 </span><span><?php echo esc_html($statsControl->find('period', 'months', '1')); ?></span>
98
+ <span>Month #2 </span><span><?php echo esc_html($statsControl->find('period', 'months', '2')); ?></span>
99
+ <span>Month #3 </span><span><?php echo esc_html($statsControl->find('period', 'months', '3')); ?></span>
100
+ <span>Month #4 </span><span><?php echo esc_html($statsControl->find('period', 'months', '4')); ?></span>
101
  </div>
102
  </div> <!-- stats -->
103
 
112
  $notices = $noticeController->getNotices();
113
  ?>
114
 
115
+ <h3>Notices (<?php echo esc_html(count($notices)); ?>)</h3>
116
  <div class='table notices'>
117
 
118
  <div class='head'>
122
  <?php foreach ($notices as $noticeObj): ?>
123
 
124
  <div>
125
+ <span><?php echo esc_html($noticeObj->getID()); ?></span>
126
  <span><?php echo ($noticeObj->isDone()) ? 'Y' : 'N'; ?> </span>
127
  <span><?php echo ($noticeObj->isDismissed()) ? 'Y' : 'N'; ?> </span>
128
  <span><?php echo ($noticeObj->isPersistent()) ? 'Y' : 'N'; ?> </span>
192
  <option>All</option>
193
  <?php foreach($queues as $name => $q)
194
  {
195
+ echo "<option>" . esc_attr($name) . "</option>";
196
  }
197
  ?>
198
  </select>
class/view/settings/part-general.php CHANGED
@@ -1,7 +1,11 @@
1
- <?php namespace ShortPixel; ?>
2
- <section id="tab-settings" <?php echo ($this->display_part == 'settings') ? ' class="sel-tab" ' :''; ?> >
 
 
 
 
3
  <h2><a class='tab-link' href='javascript:void(0);' data-id="tab-settings">
4
- <?php _e('General','shortpixel-image-optimiser');?></a>
5
  </h2>
6
 
7
  <div class="wp-shortpixel-options wp-shortpixel-tab-content" style="visibility: hidden">
@@ -10,7 +14,7 @@
10
  <table class="form-table">
11
  <tbody>
12
  <tr>
13
- <th scope="row"><label for="key"><?php _e('API Key:','shortpixel-image-optimiser');?></label></th>
14
  <td>
15
 
16
  <?php
@@ -28,7 +32,7 @@
28
 
29
  if($showApiKey) {
30
  $canValidate = true;?>
31
- <input name="key" type="text" id="key" value="<?php echo( $view->data->apiKey );?>"
32
  class="regular-text" <?php echo($editApiKey ? "" : 'disabled') ?> <?php echo $this->is_verifiedkey ? 'onkeyup="ShortPixel.apiKeyChanged()"' : '' ?>>
33
  <?php
34
  }
@@ -38,21 +42,21 @@
38
  if( $this->hide_api_key ) {
39
  echo("********************");
40
  } else {
41
- _e('Multisite API Key','shortpixel-image-optimiser');
42
  }
43
  ?>" class="regular-text">
44
  <?php } ?>
45
  <input type="hidden" name="validate" id="valid" value=""/>
46
  <span class="spinner" id="pluginemail_spinner" style="float:none;"></span>
47
- <button type="button" id="validate" class="button button-primary" title="<?php _e('Validate the provided API key','shortpixel-image-optimiser');?>"
48
  onclick="ShortPixel.validateKey(this)" <?php echo $canValidate ? "" : "disabled"?> <?php echo $this->is_verifiedkey ? 'style="display:none;"' : '' ?>>
49
- <?php _e('Save settings & validate','shortpixel-image-optimiser');?>
50
  </button>
51
  <span class="shortpixel-key-valid" <?php echo $this->is_verifiedkey ? '' : 'style="display:none;"' ?>>
52
- <span class="dashicons dashicons-yes"></span><?php _e('Your API key is valid.','shortpixel-image-optimiser');?>
53
  </span>
54
  <?php if($this->is_constant_key) { ?>
55
- <p class="settings-info"><?php _e('Key defined in wp-config.php.','shortpixel-image-optimiser');?></p>
56
  <?php } ?>
57
 
58
  </td>
@@ -63,46 +67,48 @@
63
  <?php } else { //if valid key we display the rest of the options ?>
64
  <tr>
65
  <th scope="row">
66
- <label for="compressionType"><?php _e('Compression type:','shortpixel-image-optimiser');?></label>
67
  </th>
68
  <td>
69
 
70
- <input type="hidden" id="compressionType-database" value="<?php echo $view->data->compressionType ?>">
71
  <div class="shortpixel-compression">
72
  <div class="shortpixel-compression-options">
73
- <label class="lossy" title="<?php _e('This is the recommended option in most cases, producing results that look the same as the original to the human eye.','shortpixel-image-optimiser');?>">
74
- <input type="radio" class="shortpixel-radio-lossy" name="compressionType" value="1" <?php echo( $view->data->compressionType == 1 ? "checked" : "" );?>><span><?php _e('Lossy','shortpixel-image-optimiser');?></span>
75
  </label>
76
 
77
- <label class="glossy" title="<?php _e('Best option for photographers and other professionals that use very high quality images on their sites and want best compression while keeping the quality untouched.','shortpixel-image-optimiser');?>">
78
- <input type="radio" class="shortpixel-radio-glossy" name="compressionType" value="2" <?php echo( $view->data->compressionType == 2 ? "checked" : "" );?>><span><?php _e('Glossy','shortpixel-image-optimiser');?></span>
79
  </label>
80
 
81
- <label class="lossless" title="<?php _e('Make sure not a single pixel looks different in the optimized image compared with the original. In some rare cases you will need to use this type of compression. Some technical drawings or images from vector graphics are possible situations.','shortpixel-image-optimiser');?>">
82
- <input type="radio" class="shortpixel-radio-lossless" name="compressionType" value="0" <?php echo( $view->data->compressionType == 0 ? "checked" : "" );?>><span><?php _e('Lossless','shortpixel-image-optimiser');?></span>
83
  </label>
84
 
85
- <?php printf(__('%s Run a few tests%s to help you decide.', 'shortpixel-image-optimiser'), '<a href="https://shortpixel.com/online-image-compression" style="margin-left:20px;" target="_blank">', '</a>'); ?>
86
 
87
  <div class="spio-inline-help"><span class="dashicons dashicons-editor-help" title="Click for more info" data-link="https://shortpixel.com/knowledge-base/article/11-lossy-glossy-or-lossless-which-one-is-the-best-for-me"></span></div>
88
 
89
  <p class="settings-info shortpixel-radio-info shortpixel-radio-lossy" <?php echo( $view->data->compressionType == 1 ? "" : 'style="display:none"' );?>>
90
- <?php _e('<b>Lossy compression (recommended): </b>offers the best compression rate.</br> This is the recommended option for most users, producing results that look the same as the original to the human eye.','shortpixel-image-optimiser');?>
91
  </p>
92
  <p class="settings-info shortpixel-radio-info shortpixel-radio-glossy" <?php echo( $view->data->compressionType == 2 ? "" : 'style="display:none"' );?>>
93
- <?php _e('<b>Glossy compression: </b>creates images that are almost pixel-perfect identical with the originals.</br> Best option for photographers and other professionals that use very high quality images on their sites and want the best compression while keeping the quality untouched.','shortpixel-image-optimiser');?>
 
94
  <a href="https://shortpixel.com/blog/glossy-image-optimization-for-photographers/" target="_blank" class="shortpixel-help-link">
95
- <span class="dashicons dashicons-editor-help"></span><?php _e('More info about glossy','shortpixel-image-optimiser');?>
96
- </a></p>
 
97
  <p class="settings-info shortpixel-radio-info shortpixel-radio-lossless" <?php echo( $view->data->compressionType == 0 ? "" : 'style="display:none"' );?>>
98
- <?php _e('<b>Lossless compression: </b> the resulting image is pixel-identical with the original image.</br>Make sure not a single pixel looks different in the optimized image compared with the original.
99
- In some rare cases you will need to use this type of compression. Some technical drawings or images from vector graphics are possible situations.','shortpixel-image-optimiser');?>
100
  </p>
101
  </div>
102
 
103
  </div>
104
  <script>
105
-
106
  function shortpixelCompressionLevelInfo() {
107
  jQuery(".shortpixel-compression p").css("display", "none");
108
  jQuery(".shortpixel-compression p." + jQuery(".shortpixel-compression-options input:radio:checked").attr('class')).css("display", "block");
@@ -116,15 +122,15 @@
116
  <th scope="row">&nbsp;</th>
117
  <td>
118
  <div class='compression-notice warning'>
119
- <p><?php _e( 'This compression type will apply only to new or unprocessed images. Images that were already processed will not be re-optimized. If you want to change the compression type of already optimized images, <a href="options-general.php?page=wp-shortpixel-settings&part=tools">restore them from the backup</a> first.', 'shortpixel-image-optimiser' ); ?></p>
120
- <p><?php _e('The current optimization processes in the queue will be stopped.', 'shortpixel-image-optimiser'); ?></p>
121
 
122
  </div>
123
  </td>
124
  </tr>
125
 
126
  <tr>
127
- <th scope="row"><?php _e('Thumbnail compression:','shortpixel-image-optimiser');?></th>
128
  <td>
129
 
130
  <div class='switch_button'>
@@ -132,19 +138,19 @@
132
  <label>
133
  <input type="checkbox" class="switch" name="processThumbnails" value="1" <?php checked($view->data->processThumbnails, '1');?>>
134
  <div class="the_switch">&nbsp; </div>
135
- <?php printf(__('Apply compression also to %s image thumbnails.%s ','shortpixel-image-optimiser'), '<strong>', '</strong>'); ?>
136
  </label>
137
  </div>
138
 
139
  <p class="settings-info">
140
- <?php _e('It is highly recommended that you optimize the thumbnails as they are usually the images most viewed by end users and can generate most traffic.<br>Please note that thumbnails count up to your total quota.','shortpixel-image-optimiser');?>
141
  </p>
142
 
143
  </td>
144
  </tr>
145
 
146
  <tr>
147
- <th scope="row"><?php _e('Backup','shortpixel-image-optimiser');?></th>
148
  <td>
149
 
150
 
@@ -153,20 +159,20 @@
153
  <label>
154
  <input type="checkbox" class="switch" name="backupImages" value="1" <?php checked($view->data->backupImages, '1');?>>
155
  <div class="the_switch">&nbsp; </div>
156
- <?php _e('Create a backup of the original images, saved on your server in /wp-content/uploads/ShortpixelBackups/.','shortpixel-image-optimiser');?>
157
  </label>
158
  </div>
159
 
160
- <p class="settings-info"><?php _e('You can remove the backup folder at any moment but it is best to keep a local/cloud copy, in case you want to restore the optimized files to originals or re-optimize the images using a different compression type.','shortpixel-image-optimiser');?></p>
161
  </td>
162
  </tr>
163
 
164
  <tr class='view-notice-row backup_warning'>
165
  <th scope='row'>&nbsp;</th>
166
- <td><div class='view-notice warning'><p><?php _e('Make sure you have a backup in place. When optimizing, ShortPixel will overwrite your images without recovery, which may result in lost images.', 'shortpixel-image-optimiser') ?></p></div></td>
167
  </tr>
168
  <tr>
169
- <th scope="row"><?php _e('Remove EXIF','shortpixel-image-optimiser');?></th>
170
  <td>
171
 
172
  <div class='switch_button'>
@@ -175,7 +181,7 @@
175
  <label>
176
  <input type="checkbox" class="switch" name="removeExif" value="1" <?php checked($view->data->keepExif, 0);?>>
177
  <div class="the_switch">&nbsp; </div>
178
- <?php _e('Remove the EXIF tag of the image (recommended).','shortpixel-image-optimiser');?>
179
  </label>
180
  </div>
181
 
@@ -185,25 +191,16 @@
185
  <tr class='exif_warning view-notice-row'>
186
  <th scope="row">&nbsp;</th>
187
  <td>
188
- <div class='view-notice warning'><p><?php printf(__('Warning - Converting from PNG to JPG will %s not %s keep the EXIF information!'), "<strong>","</strong>"); ?></p></div>
189
  </td>
190
  </tr>
191
 
192
- <?php /* Disabled, pending review <tr>
193
- <th scope="row"><?php _e('OptIn for Help Services','shortpixel-image-optimiser');?></th>
194
- <td>
195
- <input name="helpscoutOptin" type="checkbox" id="helpscoutOptin" value="1" <?php checked($view->data->helpscoutOptin, 1);?>>
196
- <label for="helpscoutOptin"><?php _e('Show me InAdmin Help','shortpixel-image-optimiser');?></label>
197
- <p class="settings-info"> <?php _e('We use HelpScout and QuriOBot to better serve your questions. You have give permission so we can answer your questions straight in your admin panel','shortpixel-image-optimiser');?></p>
198
-
199
- </td>
200
- </tr> */ ?>
201
 
202
  <?php $imagick = (\wpSPIO()->env()->hasImagick()) ? 1 : 0; ?>
203
- <tr class='exif_imagick_warning view-notice-row' data-imagick="<?php echo $imagick ?>">
204
  <th scope="row">&nbsp;</th>
205
  <td>
206
- <div class='view-notice warning'><p><?php printf(__('Warning - Imagick library not detected on server. WordPress will use another library to resize images, which may result in loss of EXIF information'), "<strong>","</strong>"); ?></p></div>
207
  </td>
208
  </tr>
209
 
@@ -211,46 +208,46 @@
211
  <?php $resizeDisabled = (! $this->view->data->resizeImages) ? 'disabled' : '';
212
  // @todo Inline styling here can be decluttered.
213
  ?>
214
- <th scope="row"><?php _e('Resize large images','shortpixel-image-optimiser');?></th>
215
  <td>
216
 
217
  <div class='switch_button'>
218
  <label>
219
  <input type="checkbox" class="switch" name="resizeImages" id='resize' value="1" <?php checked($view->data->resizeImages, true);?>>
220
  <div class="the_switch">&nbsp; </div>
221
- <?php _e('to maximum','shortpixel-image-optimiser') ?>
222
  </label>
223
  </div>
224
 
225
 
226
 
227
  <input type="number" min="1" max="20000" name="resizeWidth" id="width" style="width:80px" class="resize-sizes"
228
- value="<?php echo( $view->data->resizeWidth > 0 ? $view->data->resizeWidth : min(1200, $view->minSizes['width']) );?>" <?php echo( $resizeDisabled );?>/> <?php
229
- _e('pixels wide &times;','shortpixel-image-optimiser');?>
230
 
231
  <input type="number" min="1" max="20000" name="resizeHeight" id="height" class="resize-sizes" style="width:80px"
232
- value="<?php echo( $view->data->resizeHeight > 0 ? $view->data->resizeHeight : min(1200, $view->minSizes['height']) );?>" <?php echo( $resizeDisabled );?>/> <?php
233
- _e('pixels high (preserves the original aspect ratio and doesn\'t crop the image)','shortpixel-image-optimiser');?>
234
 
235
- <input type="hidden" id="min-resizeWidth" value="<?php echo($view->minSizes['width']);?>" data-nicename="<?php _e('Width', 'shortpixel-image-optimiser'); ?>" />
236
 
237
- <input type="hidden" id="min-resizeHeight" value="<?php echo($view->minSizes['height']);?>" data-nicename="<?php _e('Height', 'shortpixel-image-optimiser'); ?>"/>
238
 
239
  <p class="settings-info">
240
- <?php _e('Recommended for large photos, like the ones taken with your phone. Saved space can go up to 80% or more after resizing. Please note that this option does not prevent thumbnails from being created that should be larger than the selected dimensions, but these thumbnails will also be resized to the dimensions selected here.','shortpixel-image-optimiser');?>
241
 
242
 
243
  </p>
244
  <?php if(false) { ?>
245
  <div style="margin-top: 10px;">
246
  <input type="radio" name="resizeType" id="resize_type_outer" value="outer" <?php echo($view->data->resizeType == 'inner' ? '' : 'checked') ?> style="margin: -50px 10px 60px 0;">
247
- <img alt="<?php _e('Resize outer','shortpixel-image-optimiser'); ?>" src="<?php echo(wpSPIO()->plugin_url('res/img/resize-outer.png' ));?>"
248
- srcset='<?php echo(wpSPIO()->plugin_url('res/img/resize-outer.png' ));?> 1x, <?php echo(wpSPIO()->plugin_url('res/img/resize-outer@2x.png' ));?> 2x'
249
- title="<?php _e('Sizes will be greater or equal to the corresponding value. For example, if you set the resize dimensions at 1000x1200, an image of 2000x3000px will be resized to 1000x1500px while an image of 3000x2000px will be resized to 1800x1200px','shortpixel-image-optimiser');?>">
250
- <input type="radio" name="resizeType" id="resize_type_inner" value="inner" <?php echo($view->data->resizeType == 'inner' ? 'checked' : '') ?> style="margin: -50px 10px 60px 35px;">
251
- <img alt="<?php _e('Resize inner','shortpixel-image-optimiser'); ?>" src="<?php echo(wpSPIO()->plugin_url('res/img/resize-inner.png' ));?>"
252
- srcset='<?php echo(wpSPIO()->plugin_url('res/img/resize-inner.png' ));?> 1x, <?php echo(wpSPIO()->plugin_url('res/img/resize-inner@2x.png' ));?> 2x'
253
- title="<?php _e('Sizes will be smaller or equal to the corresponding value. For example, if you set the resize dimensions at 1000x1200, an image of 2000x3000px will be resized to 800x1200px while an image of 3000x2000px will be resized to 1000x667px','shortpixel-image-optimiser');?>">
254
 
255
  </div>
256
  <?php } ?>
@@ -299,17 +296,17 @@
299
  </style>
300
  <div class="resize-type-wrap" <?php echo( $view->data->resizeImages ? '' : 'style="display:none;"' );?>>
301
  <div class="resize-options-wrap">
302
- <label title="<?php _e('Sizes will be greater or equal to the corresponding value. For example, if you set the resize dimensions at 1000x1200, an image of 2000x3000px will be resized to 1000x1500px while an image of 3000x2000px will be resized to 1800x1200px','shortpixel-image-optimiser');?>">
303
  <input type="radio" name="resizeType" id="resize_type_outer" value="outer" <?= $view->data->resizeType == 'inner' ? '' : 'checked'; ?>>
304
- <?= __( 'Cover', 'shortpixel-image-optimiser' ); ?>
305
  </label><br>
306
- <label title="<?php _e('Sizes will be smaller or equal to the corresponding value. For example, if you set the resize dimensions at 1000x1200, an image of 2000x3000px will be resized to 800x1200px while an image of 3000x2000px will be resized to 1000x667px','shortpixel-image-optimiser');?>">
307
  <input type="radio" name="resizeType" id="resize_type_inner" value="inner" <?= $view->data->resizeType == 'inner' ? 'checked' : ''; ?>>
308
- <?= __( 'Contain', 'shortpixel-image-optimiser' ); ?>
309
  </label><br>
310
  <div style="display:inline-block;margin-top: 15px;"><a href="https://shortpixel.com/knowledge-base/article/208-can-shortpixel-automatically-resize-new-image-uploads/" class="shortpixel-help-link" target="_blank">
311
 
312
- <span class="dashicons dashicons-editor-help"></span><?php _e('What is this?','shortpixel-image-optimiser');?></a>
313
  </div>
314
 
315
  </div>
@@ -324,14 +321,12 @@
324
  ?>
325
  <div class="presentation-wrap">
326
  <div class="spai-resize-frame"></div>
327
- <img class="spai-resize-img" src="<?php echo(wpSPIO()->plugin_url('res/img/resize-type.png'));?>" data-width="300" data-height="160"
328
- srcset="<?php echo(wpSPIO()->plugin_url('res/img/resize-type@2x.png'));?> 2x" alt="">
329
  </div>
330
 
331
  </div>
332
- <script type="text/javascript">
333
 
334
- </script>
335
  </td>
336
  </tr>
337
  </tbody>
@@ -340,8 +335,8 @@
340
 
341
  <?php } ?>
342
  <p class="submit">
343
- <input type="submit" name="save" id="save" class="button button-primary" title="<?php _e('Save Changes','shortpixel-image-optimiser');?>" value="<?php _e('Save Changes','shortpixel-image-optimiser');?>"> &nbsp;
344
- <input type="submit" name="save_bulk" id="bulk" class="button button-primary" title="<?php _e('Save and go to the Bulk Processing page','shortpixel-image-optimiser');?>" value="<?php _e('Save and Go to Bulk Process','shortpixel-image-optimiser');?>"> &nbsp;
345
  </p>
346
  </div>
347
 
1
+ <?php
2
+ namespace ShortPixel;
3
+
4
+ ?>
5
+
6
+ <section id="tab-settings" class="<?php echo ($this->display_part == 'settings') ? 'sel-tab' :''; ?>" >
7
  <h2><a class='tab-link' href='javascript:void(0);' data-id="tab-settings">
8
+ <?php esc_html_e('General','shortpixel-image-optimiser');?></a>
9
  </h2>
10
 
11
  <div class="wp-shortpixel-options wp-shortpixel-tab-content" style="visibility: hidden">
14
  <table class="form-table">
15
  <tbody>
16
  <tr>
17
+ <th scope="row"><label for="key"><?php esc_html_e('API Key:','shortpixel-image-optimiser');?></label></th>
18
  <td>
19
 
20
  <?php
32
 
33
  if($showApiKey) {
34
  $canValidate = true;?>
35
+ <input name="key" type="text" id="key" value="<?php echo esc_attr( $view->data->apiKey );?>"
36
  class="regular-text" <?php echo($editApiKey ? "" : 'disabled') ?> <?php echo $this->is_verifiedkey ? 'onkeyup="ShortPixel.apiKeyChanged()"' : '' ?>>
37
  <?php
38
  }
42
  if( $this->hide_api_key ) {
43
  echo("********************");
44
  } else {
45
+ esc_html_e('Multisite API Key','shortpixel-image-optimiser');
46
  }
47
  ?>" class="regular-text">
48
  <?php } ?>
49
  <input type="hidden" name="validate" id="valid" value=""/>
50
  <span class="spinner" id="pluginemail_spinner" style="float:none;"></span>
51
+ <button type="button" id="validate" class="button button-primary" title="<?php esc_html_e('Validate the provided API key','shortpixel-image-optimiser');?>"
52
  onclick="ShortPixel.validateKey(this)" <?php echo $canValidate ? "" : "disabled"?> <?php echo $this->is_verifiedkey ? 'style="display:none;"' : '' ?>>
53
+ <?php esc_html_e('Save settings & validate','shortpixel-image-optimiser');?>
54
  </button>
55
  <span class="shortpixel-key-valid" <?php echo $this->is_verifiedkey ? '' : 'style="display:none;"' ?>>
56
+ <span class="dashicons dashicons-yes"></span><?php esc_html_e('Your API key is valid.','shortpixel-image-optimiser');?>
57
  </span>
58
  <?php if($this->is_constant_key) { ?>
59
+ <p class="settings-info"><?php esc_html_e('Key defined in wp-config.php.','shortpixel-image-optimiser');?></p>
60
  <?php } ?>
61
 
62
  </td>
67
  <?php } else { //if valid key we display the rest of the options ?>
68
  <tr>
69
  <th scope="row">
70
+ <label for="compressionType"><?php esc_html_e('Compression type:','shortpixel-image-optimiser');?></label>
71
  </th>
72
  <td>
73
 
74
+ <input type="hidden" id="compressionType-database" value="<?php echo esc_attr($view->data->compressionType) ?>">
75
  <div class="shortpixel-compression">
76
  <div class="shortpixel-compression-options">
77
+ <label class="lossy" title="<?php esc_html_e('This is the recommended option in most cases, producing results that look the same as the original to the human eye.','shortpixel-image-optimiser');?>">
78
+ <input type="radio" class="shortpixel-radio-lossy" name="compressionType" value="1" <?php echo( $view->data->compressionType == 1 ? "checked" : "" );?>><span><?php esc_html_e('Lossy','shortpixel-image-optimiser');?></span>
79
  </label>
80
 
81
+ <label class="glossy" title="<?php esc_html_e('Best option for photographers and other professionals that use very high quality images on their sites and want best compression while keeping the quality untouched.','shortpixel-image-optimiser');?>">
82
+ <input type="radio" class="shortpixel-radio-glossy" name="compressionType" value="2" <?php echo( $view->data->compressionType == 2 ? "checked" : "" );?>><span><?php esc_html_e('Glossy','shortpixel-image-optimiser');?></span>
83
  </label>
84
 
85
+ <label class="lossless" title="<?php esc_html_e('Make sure not a single pixel looks different in the optimized image compared with the original. In some rare cases you will need to use this type of compression. Some technical drawings or images from vector graphics are possible situations.','shortpixel-image-optimiser');?>">
86
+ <input type="radio" class="shortpixel-radio-lossless" name="compressionType" value="0" <?php echo( $view->data->compressionType == 0 ? "checked" : "" );?>><span><?php esc_html_e('Lossless','shortpixel-image-optimiser');?></span>
87
  </label>
88
 
89
+ <?php printf(esc_html__('%s Run a few tests%s to help you decide.', 'shortpixel-image-optimiser'), '<a href="https://shortpixel.com/online-image-compression" style="margin-left:20px;" target="_blank">', '</a>'); ?>
90
 
91
  <div class="spio-inline-help"><span class="dashicons dashicons-editor-help" title="Click for more info" data-link="https://shortpixel.com/knowledge-base/article/11-lossy-glossy-or-lossless-which-one-is-the-best-for-me"></span></div>
92
 
93
  <p class="settings-info shortpixel-radio-info shortpixel-radio-lossy" <?php echo( $view->data->compressionType == 1 ? "" : 'style="display:none"' );?>>
94
+ <?php printf(esc_html__('%sLossy compression (recommended): %s offers the best compression rate. %s This is the recommended option for most users, producing results that look the same as the original to the human eye.','shortpixel-image-optimiser'),'<b>','</b>', '<br />');?>
95
  </p>
96
  <p class="settings-info shortpixel-radio-info shortpixel-radio-glossy" <?php echo( $view->data->compressionType == 2 ? "" : 'style="display:none"' );?>>
97
+ <?php printf(esc_html__('%sGlossy compression: %s creates images that are almost pixel-perfect identical with the originals. %s Best option for photographers and other professionals that use very high quality images on their sites and want the best compression while keeping the quality untouched.','shortpixel-image-optimiser'), '<b>','</b>', '<br>');?>
98
+
99
  <a href="https://shortpixel.com/blog/glossy-image-optimization-for-photographers/" target="_blank" class="shortpixel-help-link">
100
+ <span class="dashicons dashicons-editor-help"></span><?php esc_html_e('More info about glossy','shortpixel-image-optimiser');?>
101
+ </a>
102
+ </p>
103
  <p class="settings-info shortpixel-radio-info shortpixel-radio-lossless" <?php echo( $view->data->compressionType == 0 ? "" : 'style="display:none"' );?>>
104
+ <?php printf(esc_html__('%s Lossless compression: %s the resulting image is pixel-identical with the original image. %sMake sure not a single pixel looks different in the optimized image compared with the original.
105
+ In some rare cases you will need to use this type of compression. Some technical drawings or images from vector graphics are possible situations.','shortpixel-image-optimiser'),'<b>','</b>', '<br>');?>
106
  </p>
107
  </div>
108
 
109
  </div>
110
  <script>
111
+ <!-- @todo Inline JS -->
112
  function shortpixelCompressionLevelInfo() {
113
  jQuery(".shortpixel-compression p").css("display", "none");
114
  jQuery(".shortpixel-compression p." + jQuery(".shortpixel-compression-options input:radio:checked").attr('class')).css("display", "block");
122
  <th scope="row">&nbsp;</th>
123
  <td>
124
  <div class='compression-notice warning'>
125
+ <p><?php printf(esc_html__('This compression type will apply only to new or unprocessed images. Images that were already processed will not be re-optimized. If you want to change the compression type of already optimized images, %s restore them from the backup %s first.', 'shortpixel-image-optimiser' ),'<a href="options-general.php?page=wp-shortpixel-settings&part=tools">', '</a>'); ?></p>
126
+ <p><?php esc_html_e('The current optimization processes in the queue will be stopped.', 'shortpixel-image-optimiser'); ?></p>
127
 
128
  </div>
129
  </td>
130
  </tr>
131
 
132
  <tr>
133
+ <th scope="row"><?php esc_html_e('Thumbnail compression:','shortpixel-image-optimiser');?></th>
134
  <td>
135
 
136
  <div class='switch_button'>
138
  <label>
139
  <input type="checkbox" class="switch" name="processThumbnails" value="1" <?php checked($view->data->processThumbnails, '1');?>>
140
  <div class="the_switch">&nbsp; </div>
141
+ <?php printf(esc_html__('Apply compression also to %s image thumbnails.%s ','shortpixel-image-optimiser'), '<strong>', '</strong>'); ?>
142
  </label>
143
  </div>
144
 
145
  <p class="settings-info">
146
+ <?php printf(esc_html__('It is highly recommended that you optimize the thumbnails as they are usually the images most viewed by end users and can generate most traffic. %s Please note that thumbnails count up to your total quota.','shortpixel-image-optimiser'), '<br>'); ?>
147
  </p>
148
 
149
  </td>
150
  </tr>
151
 
152
  <tr>
153
+ <th scope="row"><?php esc_html_e('Backup','shortpixel-image-optimiser');?></th>
154
  <td>
155
 
156
 
159
  <label>
160
  <input type="checkbox" class="switch" name="backupImages" value="1" <?php checked($view->data->backupImages, '1');?>>
161
  <div class="the_switch">&nbsp; </div>
162
+ <?php esc_html_e('Create a backup of the original images, saved on your server in /wp-content/uploads/ShortpixelBackups/.','shortpixel-image-optimiser');?>
163
  </label>
164
  </div>
165
 
166
+ <p class="settings-info"><?php esc_html_e('You can remove the backup folder at any moment but it is best to keep a local/cloud copy, in case you want to restore the optimized files to originals or re-optimize the images using a different compression type.','shortpixel-image-optimiser');?></p>
167
  </td>
168
  </tr>
169
 
170
  <tr class='view-notice-row backup_warning'>
171
  <th scope='row'>&nbsp;</th>
172
+ <td><div class='view-notice warning'><p><?php esc_html_e('Make sure you have a backup in place. When optimizing, ShortPixel will overwrite your images without recovery, which may result in lost images.', 'shortpixel-image-optimiser') ?></p></div></td>
173
  </tr>
174
  <tr>
175
+ <th scope="row"><?php esc_html_e('Remove EXIF','shortpixel-image-optimiser');?></th>
176
  <td>
177
 
178
  <div class='switch_button'>
181
  <label>
182
  <input type="checkbox" class="switch" name="removeExif" value="1" <?php checked($view->data->keepExif, 0);?>>
183
  <div class="the_switch">&nbsp; </div>
184
+ <?php esc_html_e('Remove the EXIF tag of the image (recommended).','shortpixel-image-optimiser');?>
185
  </label>
186
  </div>
187
 
191
  <tr class='exif_warning view-notice-row'>
192
  <th scope="row">&nbsp;</th>
193
  <td>
194
+ <div class='view-notice warning'><p><?php printf(esc_html__('Warning - Converting from PNG to JPG will %s not %s keep the EXIF information!'), "<strong>","</strong>"); ?></p></div>
195
  </td>
196
  </tr>
197
 
 
 
 
 
 
 
 
 
 
198
 
199
  <?php $imagick = (\wpSPIO()->env()->hasImagick()) ? 1 : 0; ?>
200
+ <tr class='exif_imagick_warning view-notice-row' data-imagick="<?php echo esc_attr($imagick) ?>">
201
  <th scope="row">&nbsp;</th>
202
  <td>
203
+ <div class='view-notice warning'><p><?php printf(esc_html__('Warning - Imagick library not detected on server. WordPress will use another library to resize images, which may result in loss of EXIF information'), "<strong>","</strong>"); ?></p></div>
204
  </td>
205
  </tr>
206
 
208
  <?php $resizeDisabled = (! $this->view->data->resizeImages) ? 'disabled' : '';
209
  // @todo Inline styling here can be decluttered.
210
  ?>
211
+ <th scope="row"><?php esc_html_e('Resize large images','shortpixel-image-optimiser');?></th>
212
  <td>
213
 
214
  <div class='switch_button'>
215
  <label>
216
  <input type="checkbox" class="switch" name="resizeImages" id='resize' value="1" <?php checked($view->data->resizeImages, true);?>>
217
  <div class="the_switch">&nbsp; </div>
218
+ <?php esc_html_e('to maximum','shortpixel-image-optimiser') ?>
219
  </label>
220
  </div>
221
 
222
 
223
 
224
  <input type="number" min="1" max="20000" name="resizeWidth" id="width" style="width:80px" class="resize-sizes"
225
+ value="<?php echo esc_attr( $view->data->resizeWidth > 0 ? $view->data->resizeWidth : min(1200, $view->minSizes['width']) );?>" <?php echo esc_attr( $resizeDisabled );?>/> <?php
226
+ esc_html_e('pixels wide &times;','shortpixel-image-optimiser');?>
227
 
228
  <input type="number" min="1" max="20000" name="resizeHeight" id="height" class="resize-sizes" style="width:80px"
229
+ value="<?php echo esc_attr( $view->data->resizeHeight > 0 ? $view->data->resizeHeight : min(1200, $view->minSizes['height']) );?>" <?php echo esc_attr( $resizeDisabled );?>/> <?php
230
+ esc_html_e('pixels high (preserves the original aspect ratio and doesn\'t crop the image)','shortpixel-image-optimiser');?>
231
 
232
+ <input type="hidden" id="min-resizeWidth" value="<?php echo esc_attr($view->minSizes['width']);?>" data-nicename="<?php esc_html_e('Width', 'shortpixel-image-optimiser'); ?>" />
233
 
234
+ <input type="hidden" id="min-resizeHeight" value="<?php echo esc_attr($view->minSizes['height']);?>" data-nicename="<?php esc_html_e('Height', 'shortpixel-image-optimiser'); ?>"/>
235
 
236
  <p class="settings-info">
237
+ <?php esc_html_e('Recommended for large photos, like the ones taken with your phone. Saved space can go up to 80% or more after resizing. Please note that this option does not prevent thumbnails from being created that should be larger than the selected dimensions, but these thumbnails will also be resized to the dimensions selected here.','shortpixel-image-optimiser');?>
238
 
239
 
240
  </p>
241
  <?php if(false) { ?>
242
  <div style="margin-top: 10px;">
243
  <input type="radio" name="resizeType" id="resize_type_outer" value="outer" <?php echo($view->data->resizeType == 'inner' ? '' : 'checked') ?> style="margin: -50px 10px 60px 0;">
244
+ <img alt="<?php esc_html_e('Resize outer','shortpixel-image-optimiser'); ?>" src="<?php echo esc_url(wpSPIO()->plugin_url('res/img/resize-outer.png' ));?>"
245
+ srcset='<?php echo esc_url(wpSPIO()->plugin_url('res/img/resize-outer.png' ));?> 1x, <?php echo esc_url(wpSPIO()->plugin_url('res/img/resize-outer@2x.png' ));?> 2x'
246
+ title="<?php esc_html_e('Sizes will be greater or equal to the corresponding value. For example, if you set the resize dimensions at 1000x1200, an image of 2000x3000px will be resized to 1000x1500px while an image of 3000x2000px will be resized to 1800x1200px','shortpixel-image-optimiser');?>">
247
+ <input type="radio" name="resizeType" id="resize_type_inner" value="inner" <?php echo esc_attr($view->data->resizeType == 'inner' ? 'checked' : '') ?> style="margin: -50px 10px 60px 35px;">
248
+ <img alt="<?php esc_html_e('Resize inner','shortpixel-image-optimiser'); ?>" src="<?php echo esc_url(wpSPIO()->plugin_url('res/img/resize-inner.png' ));?>"
249
+ srcset='<?php echo esc_url(wpSPIO()->plugin_url('res/img/resize-inner.png' ));?> 1x, <?php echo esc_url(wpSPIO()->plugin_url('res/img/resize-inner@2x.png' ));?> 2x'
250
+ title="<?php esc_html_e('Sizes will be smaller or equal to the corresponding value. For example, if you set the resize dimensions at 1000x1200, an image of 2000x3000px will be resized to 800x1200px while an image of 3000x2000px will be resized to 1000x667px','shortpixel-image-optimiser');?>">
251
 
252
  </div>
253
  <?php } ?>
296
  </style>
297
  <div class="resize-type-wrap" <?php echo( $view->data->resizeImages ? '' : 'style="display:none;"' );?>>
298
  <div class="resize-options-wrap">
299
+ <label title="<?php esc_html_e('Sizes will be greater or equal to the corresponding value. For example, if you set the resize dimensions at 1000x1200, an image of 2000x3000px will be resized to 1000x1500px while an image of 3000x2000px will be resized to 1800x1200px','shortpixel-image-optimiser');?>">
300
  <input type="radio" name="resizeType" id="resize_type_outer" value="outer" <?= $view->data->resizeType == 'inner' ? '' : 'checked'; ?>>
301
+ <?= esc_html__( 'Cover', 'shortpixel-image-optimiser' ); ?>
302
  </label><br>
303
+ <label title="<?php esc_html_e('Sizes will be smaller or equal to the corresponding value. For example, if you set the resize dimensions at 1000x1200, an image of 2000x3000px will be resized to 800x1200px while an image of 3000x2000px will be resized to 1000x667px','shortpixel-image-optimiser');?>">
304
  <input type="radio" name="resizeType" id="resize_type_inner" value="inner" <?= $view->data->resizeType == 'inner' ? 'checked' : ''; ?>>
305
+ <?= esc_html__( 'Contain', 'shortpixel-image-optimiser' ); ?>
306
  </label><br>
307
  <div style="display:inline-block;margin-top: 15px;"><a href="https://shortpixel.com/knowledge-base/article/208-can-shortpixel-automatically-resize-new-image-uploads/" class="shortpixel-help-link" target="_blank">
308
 
309
+ <span class="dashicons dashicons-editor-help"></span><?php esc_html_e('What is this?','shortpixel-image-optimiser');?></a>
310
  </div>
311
 
312
  </div>
321
  ?>
322
  <div class="presentation-wrap">
323
  <div class="spai-resize-frame"></div>
324
+ <img class="spai-resize-img" src="<?php echo esc_url(wpSPIO()->plugin_url('res/img/resize-type.png'));?>" data-width="300" data-height="160"
325
+ srcset="<?php echo esc_url(wpSPIO()->plugin_url('res/img/resize-type@2x.png'));?> 2x" alt="">
326
  </div>
327
 
328
  </div>
 
329
 
 
330
  </td>
331
  </tr>
332
  </tbody>
335
 
336
  <?php } ?>
337
  <p class="submit">
338
+ <input type="submit" name="save" id="save" class="button button-primary" title="<?php esc_attr_e('Save Changes','shortpixel-image-optimiser');?>" value="<?php esc_attr_e('Save Changes','shortpixel-image-optimiser');?>"> &nbsp;
339
+ <input type="submit" name="save_bulk" id="bulk" class="button button-primary" title="<?php esc_attr_e('Save and go to the Bulk Processing page','shortpixel-image-optimiser');?>" value="<?php esc_attr_e('Save and Go to Bulk Process','shortpixel-image-optimiser');?>"> &nbsp;
340
  </p>
341
  </div>
342
 
class/view/settings/part-nokey.php CHANGED
@@ -27,55 +27,54 @@ elseif ($this->is_constant_key && ! $this->is_verifiedkey)
27
  }
28
 
29
  $adminEmail = get_bloginfo('admin_email');
30
- if($adminEmail == 'noreply@addendio.com') $adminEmail = false; //hack for the addendio sandbox e-mail
31
 
32
  ?>
33
  <section id="tab-settings" class="sel-tab" >
34
  <h2><a class='tab-link' href='javascript:void(0);' data-id="tab-settings">
35
- <?php _e('Join ShortPixel','shortpixel-image-optimiser');?></a>
36
  </h2>
37
  <div class="wp-shortpixel-options wp-shortpixel-tab-content">
38
  <?php if($showApiKey): ?>
39
- <h3><?php _e('Request an API Key:','shortpixel-image-optimiser');?></h3>
40
- <p style='font-size: 14px'><?php _e('If you don\'t have an API Key, you can request one for free. Just press the "Request Key" button after checking that the e-mail is correct.','shortpixel-image-optimiser');?></p>
 
41
 
42
  <table class="form-table">
43
  <tbody>
44
  <tr>
45
- <th scope="row"><label for="key"><?php _e('E-mail address:','shortpixel-image-optimiser');?></label></th>
46
  <td>
47
  <form method="POST" action="<?php echo esc_url(add_query_arg(array('noheader' => 'true', 'sp-action' => 'action_request_new_key'))) ?>"
48
  id="shortpixel-form-request-key">
49
  <?php wp_nonce_field($this->form_action, 'sp-nonce'); ?>
50
 
51
 
52
- <input name="pluginemail" type="text" id="pluginemail" value="<?php echo( $adminEmail );?>"
53
  class="regular-text">
54
 
55
  <span class="spinner" id="pluginemail_spinner" style="float:none;"></span>
56
 
57
- <button type="submit" id="request_key" class="button button-primary" title="<?php _e('Request a new API key','shortpixel-image-optimiser');?>"
58
- href="https://shortpixel.com/free-sign-up?pluginemail=<?php echo( $adminEmail );?>"
59
- >
60
- <?php _e('Request Key','shortpixel-image-optimiser');?>
61
  </button>
62
  <p class="settings-info shortpixel-settings-error" style='display:none;' id='pluginemail-error'>
63
- <b><?php _e('Please provide a valid e-mail address.', 'shortpixel-image-optimiser');?></b>
64
  </p>
65
  <p class="settings-info" id='pluginemail-info'>
66
  <?php if($adminEmail) {
67
- printf(__('<b>%s</b> is the e-mail address in your WordPress Settings. You can use it, or change it to any valid e-mail address that you own.','shortpixel-image-optimiser'), $adminEmail);
68
  } else {
69
- _e('Please input your e-mail address and press the Request Key button.','shortpixel-image-optimiser');
70
  }
71
  ?><p><span style="position:relative;">
72
  <input name="tos" type="checkbox" id="tos">
73
- <img id="tos-robo" alt="<?php _e('ShortPixel logo', 'shortpixel-image-optimiser'); ?>"
74
- src="<?php echo(wpSPIO()->plugin_url('res/img/slider.png' ));?>" style="position: absolute;left: -95px;bottom: -26px;display:none;">
75
- <img id="tos-hand" alt="<?php _e('Hand pointing', 'shortpixel-image-optimiser'); ?>"
76
- src="<?php echo(wpSPIO()->plugin_url('res/img/point.png' ));?>" style="position: absolute;left: -39px;bottom: -9px;display:none;">
77
  </span>
78
- <label for="tos"><?php _e('I have read and I agree to the <a href="https://shortpixel.com/tos" target="_blank">Terms of Service</a> and the <a href="https://shortpixel.com/privacy" target="_blank">Privacy Policy</a> (<a href="https://shortpixel.com/privacy#gdpr" target="_blank">GDPR compliant</a>).','shortpixel-image-optimiser');
79
  ?> </label></p>
80
  </p>
81
  </form>
@@ -85,10 +84,10 @@ if($adminEmail == 'noreply@addendio.com') $adminEmail = false; //hack for the ad
85
  </table>
86
  <?php endif; ?>
87
  <h3>
88
- <?php _e('Already have an API Key:','shortpixel-image-optimiser');?>
89
  </h3>
90
  <p style='font-size: 14px'>
91
- <?php _e('If you already have an API Key please input it below and press Validate.','shortpixel-image-optimiser');?>
92
  </p>
93
 
94
  <form method="POST" action="<?php echo esc_url(add_query_arg(array('noheader' => 'true', 'sp-action' => 'action_addkey'))) ?>"
@@ -98,7 +97,7 @@ if($adminEmail == 'noreply@addendio.com') $adminEmail = false; //hack for the ad
98
  <table class="form-table">
99
  <tbody>
100
  <tr>
101
- <th scope="row"><label for="key"><?php _e('API Key:','shortpixel-image-optimiser');?></label></th>
102
  <td>
103
  <?php
104
  if($showApiKey) {
@@ -107,7 +106,7 @@ if($adminEmail == 'noreply@addendio.com') $adminEmail = false; //hack for the ad
107
  $canValidate = true;
108
 
109
  ?>
110
- <input name="key" type="text" id="key" value="<?php echo( $view->data->apiKey );?>"
111
  class="regular-text" <?php echo($editApiKey ? "" : 'disabled') ?> >
112
  <?php
113
  }
@@ -115,21 +114,21 @@ if($adminEmail == 'noreply@addendio.com') $adminEmail = false; //hack for the ad
115
  $canValidate = true;?>
116
  <input name="key" type="text" id="key" disabled="true" placeholder="<?php
117
  if( $this->hide_api_key ) {
118
- echo("********************");
119
  } else {
120
- _e('Multisite API Key','shortpixel-image-optimiser');
121
  }
122
  ?>" class="regular-text">
123
  <?php } ?>
124
  <input type="hidden" name="validate" id="valid" value="validate"/>
125
  <span class="spinner" id="pluginemail_spinner" style="float:none;"></span>
126
- <button type="submit" id="validate" class="button button-primary" title="<?php _e('Validate the provided API key','shortpixel-image-optimiser');?>"
127
  >
128
- <?php _e('Validate','shortpixel-image-optimiser');?>
129
  </button>
130
 
131
  <?php if($this->is_constant_key) { ?>
132
- <p class="settings-info"><?php _e('Key defined in wp-config.php.','shortpixel-image-optimiser');?></p>
133
  <?php } ?>
134
 
135
  </td>
27
  }
28
 
29
  $adminEmail = get_bloginfo('admin_email');
 
30
 
31
  ?>
32
  <section id="tab-settings" class="sel-tab" >
33
  <h2><a class='tab-link' href='javascript:void(0);' data-id="tab-settings">
34
+ <?php esc_html_e('Join ShortPixel','shortpixel-image-optimiser');?></a>
35
  </h2>
36
  <div class="wp-shortpixel-options wp-shortpixel-tab-content">
37
  <?php if($showApiKey): ?>
38
+ <!-- // @todo Inline CSS on whole page-->
39
+ <h3><?php esc_html_e('Request an API Key:','shortpixel-image-optimiser');?></h3>
40
+ <p style='font-size: 14px'><?php esc_html_e('If you don\'t have an API Key, you can request one for free. Just press the "Request Key" button after checking that the e-mail is correct.','shortpixel-image-optimiser');?></p>
41
 
42
  <table class="form-table">
43
  <tbody>
44
  <tr>
45
+ <th scope="row"><label for="key"><?php esc_html_e('E-mail address:','shortpixel-image-optimiser');?></label></th>
46
  <td>
47
  <form method="POST" action="<?php echo esc_url(add_query_arg(array('noheader' => 'true', 'sp-action' => 'action_request_new_key'))) ?>"
48
  id="shortpixel-form-request-key">
49
  <?php wp_nonce_field($this->form_action, 'sp-nonce'); ?>
50
 
51
 
52
+ <input name="pluginemail" type="text" id="pluginemail" value="<?php echo esc_attr( sanitize_email($adminEmail) );?>"
53
  class="regular-text">
54
 
55
  <span class="spinner" id="pluginemail_spinner" style="float:none;"></span>
56
 
57
+ <button type="submit" id="request_key" class="button button-primary" title="<?php esc_html_e('Request a new API key','shortpixel-image-optimiser');?>"
58
+ href="https://shortpixel.com/free-sign-up?pluginemail=<?php echo esc_attr( esc_url($adminEmail) );?>">
59
+ <?php esc_html_e('Request Key','shortpixel-image-optimiser');?>
 
60
  </button>
61
  <p class="settings-info shortpixel-settings-error" style='display:none;' id='pluginemail-error'>
62
+ <b><?php esc_html_e('Please provide a valid e-mail address.', 'shortpixel-image-optimiser');?></b>
63
  </p>
64
  <p class="settings-info" id='pluginemail-info'>
65
  <?php if($adminEmail) {
66
+ printf(esc_html__('%s %s %s is the e-mail address in your WordPress Settings. You can use it, or change it to any valid e-mail address that you own.','shortpixel-image-optimiser'), '<b>', esc_html(sanitize_email($adminEmail)), '</b>');
67
  } else {
68
+ esc_html_e('Please input your e-mail address and press the Request Key button.','shortpixel-image-optimiser');
69
  }
70
  ?><p><span style="position:relative;">
71
  <input name="tos" type="checkbox" id="tos">
72
+ <img id="tos-robo" alt="<?php esc_html_e('ShortPixel logo', 'shortpixel-image-optimiser'); ?>"
73
+ src="<?php echo esc_url(wpSPIO()->plugin_url('res/img/slider.png' ));?>" style="position: absolute;left: -95px;bottom: -26px;display:none;">
74
+ <img id="tos-hand" alt="<?php esc_html_e('Hand pointing', 'shortpixel-image-optimiser'); ?>"
75
+ src="<?php echo esc_url(wpSPIO()->plugin_url('res/img/point.png' ));?>" style="position: absolute;left: -39px;bottom: -9px;display:none;">
76
  </span>
77
+ <label for="tos"><?php printf(esc_html__('I have read and I agree to the %s Terms of Service %s and the %s Privacy Policy %s (%s GDPR compliant %s).','shortpixel-image-optimiser'), '<a href="https://shortpixel.com/tos" target="_blank">', '</a>', '<a href="https://shortpixel.com/privacy" target="_blank">', '</a>', '<a href="https://shortpixel.com/privacy#gdpr" target="_blank">', '</a>');
78
  ?> </label></p>
79
  </p>
80
  </form>
84
  </table>
85
  <?php endif; ?>
86
  <h3>
87
+ <?php esc_html_e('Already have an API Key:','shortpixel-image-optimiser');?>
88
  </h3>
89
  <p style='font-size: 14px'>
90
+ <?php esc_html_e('If you already have an API Key please input it below and press Validate.','shortpixel-image-optimiser');?>
91
  </p>
92
 
93
  <form method="POST" action="<?php echo esc_url(add_query_arg(array('noheader' => 'true', 'sp-action' => 'action_addkey'))) ?>"
97
  <table class="form-table">
98
  <tbody>
99
  <tr>
100
+ <th scope="row"><label for="key"><?php esc_html_e('API Key:','shortpixel-image-optimiser');?></label></th>
101
  <td>
102
  <?php
103
  if($showApiKey) {
106
  $canValidate = true;
107
 
108
  ?>
109
+ <input name="key" type="text" id="key" value="<?php echo esc_attr( $view->data->apiKey );?>"
110
  class="regular-text" <?php echo($editApiKey ? "" : 'disabled') ?> >
111
  <?php
112
  }
114
  $canValidate = true;?>
115
  <input name="key" type="text" id="key" disabled="true" placeholder="<?php
116
  if( $this->hide_api_key ) {
117
+ echo esc_html("********************");
118
  } else {
119
+ esc_html_e('Multisite API Key','shortpixel-image-optimiser');
120
  }
121
  ?>" class="regular-text">
122
  <?php } ?>
123
  <input type="hidden" name="validate" id="valid" value="validate"/>
124
  <span class="spinner" id="pluginemail_spinner" style="float:none;"></span>
125
+ <button type="submit" id="validate" class="button button-primary" title="<?php esc_html_e('Validate the provided API key','shortpixel-image-optimiser');?>"
126
  >
127
+ <?php esc_html_e('Validate','shortpixel-image-optimiser');?>
128
  </button>
129
 
130
  <?php if($this->is_constant_key) { ?>
131
+ <p class="settings-info"><?php esc_html_e('Key defined in wp-config.php.','shortpixel-image-optimiser');?></p>
132
  <?php } ?>
133
 
134
  </td>
class/view/settings/part-optpie.php CHANGED
@@ -1,7 +1,6 @@
1
  <?php
2
  namespace ShortPixel;
3
 
4
-
5
  $total_circle = 289.027;
6
  $total =round($view->averageCompression);
7
 
@@ -13,9 +12,8 @@ if( $total >0 ) {
13
 
14
  <?php if ( round($view->averageCompression) > 20): ?>
15
  <div class="sp-bulk-summary">
16
- <span><?php _e('Average optimization', 'shortpixel-image-optimiser'); ?></span>
17
- <!-- <input type="text" value="<?php echo("" . round($view->averageCompression))?>" id="sp-total-optimization-dial" class="dial"> -->
18
- <a title="<?php _e('Average optimization', 'shortpixel-image-optimiser'); ?>">
19
  <svg class="opt-circle-average" viewBox="-10 0 150 140">
20
  <path class="trail" d="
21
  M 50,50
@@ -29,9 +27,9 @@ if( $total >0 ) {
29
  m 0,-46
30
  a 46,46 0 1 1 0,92
31
  a 46,46 0 1 1 0,-92
32
- " stroke-width="16" fill-opacity="0" style="stroke-dasharray: 289.027px, 289.027px; stroke-dashoffset: <?php echo $total_circle ?>">
33
  </path>
34
- <text class="text" x="52" y="55"><?php echo $total ?>%</text>
35
  </svg>
36
  </a>
37
 
1
  <?php
2
  namespace ShortPixel;
3
 
 
4
  $total_circle = 289.027;
5
  $total =round($view->averageCompression);
6
 
12
 
13
  <?php if ( round($view->averageCompression) > 20): ?>
14
  <div class="sp-bulk-summary">
15
+ <span><?php esc_html_e('Average optimization', 'shortpixel-image-optimiser'); ?></span>
16
+ <a title="<?php esc_html_e('Average optimization', 'shortpixel-image-optimiser'); ?>">
 
17
  <svg class="opt-circle-average" viewBox="-10 0 150 140">
18
  <path class="trail" d="
19
  M 50,50
27
  m 0,-46
28
  a 46,46 0 1 1 0,92
29
  a 46,46 0 1 1 0,-92
30
+ " stroke-width="16" fill-opacity="0" style="stroke-dasharray: 289.027px, 289.027px; stroke-dashoffset: <?php echo esc_html($total_circle) ?>">
31
  </path>
32
+ <text class="text" x="52" y="55"><?php echo esc_html($total) ?>%</text>
33
  </svg>
34
  </a>
35
 
class/view/settings/part-statistics.php DELETED
@@ -1,138 +0,0 @@
1
- <?php
2
- namespace ShortPixel;
3
- use \ShortPixel\Helper\UiHelper as UiHelper;
4
-
5
- $quotaData = $this->quotaData;
6
-
7
-
8
- ?>
9
-
10
- <section id="tab-stats" <?php echo ($this->display_part == 'stats') ? ' class="sel-tab" ' :''; ?>>
11
- <h2><a class='tab-link' href='javascript:void(0);' data-id="tab-stats"><?php _e('Statistics','shortpixel-image-optimiser');?></a></h2>
12
-
13
- <div class="wp-shortpixel-tab-content" style="visibility: hidden">
14
- <a id="facts"></a>
15
- <h3><?php _e('Your ShortPixel Stats','shortpixel-image-optimiser');?></h3>
16
- <table class="form-table">
17
- <tbody>
18
- <tr>
19
- <th scope="row">
20
- <?php _e('Average compression of your files:','shortpixel-image-optimiser');?>
21
- </th>
22
- <td>
23
- <strong><?php echo($view->averageCompression);?>%</strong>
24
- <div class="sp-bulk-summary">
25
- <input type="text" value="<?php echo("" . round($view->averageCompression))?>" id="sp-total-optimization-dial" class="dial">
26
- </div>
27
- <div id="sp-bulk-stats" style="display:none">
28
- <?php
29
- $under5PercentCount = (int) $view->data->under5Percent; //amount of under 5% optimized imgs.
30
-
31
- $totalOptimized = (int) $view->stats->totalOptimized;
32
-
33
- $mainOptimized = $view->stats->mainOptimized
34
- //isset($quotaData['mainProcessedFiles']) ? $quotaData['mainProcessedFiles'] : 0;
35
- ?>
36
- <div class="bulk-progress bulk-stats">
37
- <div class="label"><?php _e('Processed Images and PDFs:','shortpixel-image-optimiser');?></div><div class="stat-value"><?php echo(number_format($mainOptimized));?></div><br>
38
- <div class="label"><?php _e('Processed Thumbnails:','shortpixel-image-optimiser');?></div><div class="stat-value"><?php echo(number_format($totalOptimized - $mainOptimized));?></div><br>
39
- <div class="label totals"><?php _e('Total files processed:','shortpixel-image-optimiser');?></div><div class="stat-value"><?php echo(number_format($totalOptimized));?></div><br>
40
- <div class="label totals"><?php _e('Minus files with <5% optimization (free):','shortpixel-image-optimiser');?></div><div class="stat-value"><?php echo(number_format($under5PercentCount));?></div><br><br>
41
- <div class="label totals"><?php _e('Used quota:','shortpixel-image-optimiser');?></div><div class="stat-value"><?php echo(number_format($totalOptimized - $under5PercentCount));?></div><br>
42
- <br>
43
- <div class="label"><?php _e('Average optimization:','shortpixel-image-optimiser');?></div><div class="stat-value"><?php echo($view->averageCompression);?>%</div><br>
44
- <div class="label"><?php _e('Saved space:','shortpixel-image-optimiser');?></div><div class="stat-value"><?php echo($view->data->savedSpace);?></div>
45
- </div>
46
- </div>
47
-
48
- </td>
49
- </tr>
50
- <tr>
51
- <th scope="row">
52
- <?php _e('Disk space saved by ShortPixel:','shortpixel-image-optimiser');?>
53
- </th>
54
- <td><?php echo(UiHelper::formatBytes($view->data->savedSpace));?></td>
55
- </tr>
56
- <tr>
57
- <th scope="row">
58
- <?php _e('Bandwidth* saved by ShortPixel:','shortpixel-image-optimiser');?>
59
- </th>
60
- <td><?php echo($view->savedBandwidth);?></td>
61
- </tr>
62
- </tbody>
63
- </table>
64
-
65
- <h3><?php _e('Your ShortPixel Credits','shortpixel-image-optimiser');?></h3>
66
- <table class="form-table">
67
- <tbody>
68
- <tr>
69
- <th scope="row" bgcolor="#ffffff">
70
- <?php _e('Your monthly plan','shortpixel-image-optimiser');?>:
71
- </th>
72
- <td bgcolor="#ffffff">
73
- <?php
74
- $DateNow = time();
75
- // $DateSubscription = strtotime($quotaData['APILastRenewalDate']);
76
-
77
- $DaysToReset = $quotaData->monthly->renew;
78
- //30 - ((($DateNow - $DateSubscription) / 84600) % 30);
79
- printf(__('%s, renews in %s days, on %s ( <a href="https://shortpixel.com/login/%s" target="_blank">Need More? See the options available</a> )','shortpixel-image-optimiser'),
80
- $quotaData->monthly->text, $DaysToReset,
81
- date('M d, Y', strtotime(date('M d, Y') . ' + ' . $DaysToReset . ' days')), ( $this->hide_api_key) ? '' : $view->data->apiKey ); ?><br/>
82
- <?php printf(__('<a href="https://shortpixel.com/login/%s/tell-a-friend" target="_blank">Join our friend referral system</a> to win more credits. For each person that joins, you receive +100 image credits/month.','shortpixel-image-optimiser'),
83
- ( $this->hide_api_key ? '' : $view->data->apiKey));?>
84
- <br><br>
85
- <?php _e('Consumed: ','shortpixel-image-optimiser'); ?>
86
- <strong><?php echo( number_format( $quotaData->monthly->consumed ) ); ?></strong>
87
- <?php _e('; Remaining: ','shortpixel-image-optimiser'); ?>
88
- <strong><?php echo( number_format( $quotaData->monthly->remaining) ); ?></strong>
89
- </td>
90
- </tr>
91
- <tr>
92
- <th scope="row">
93
- <?php _e('Your One Time credits:','shortpixel-image-optimiser');?>
94
- </th>
95
- <td>
96
- <?php _e('Total: ','shortpixel-image-optimiser'); ?>
97
- <strong><?php echo( number_format($quotaData->onetime->total)); ?></strong>
98
- <br><br>
99
- <?php _e('Consumed: ','shortpixel-image-optimiser'); ?>
100
- <strong><?php echo( number_format($quotaData->onetime->consumed) ); ?></strong>
101
- <?php _e('; Remaining: ','shortpixel-image-optimiser'); ?>
102
- <strong><?php echo( number_format( $quotaData->onetime->remaining) ); ?></strong>**
103
- </td>
104
- </tr>
105
- <tr>
106
- <?php
107
-
108
- if ($this->hide_api_key)
109
- $link = 'https://shortpixel.com/login';
110
- else {
111
- $link = 'https://' . SHORTPIXEL_API . '/v2/report.php?key=' . $view->data->apiKey;
112
- }
113
- ?>
114
- <th><a href="<?php echo $link ?>" target="_blank">
115
- <?php _e('See report (last 30 days)','shortpixel-image-optimiser');?>
116
- </a></th>
117
- <td>&nbsp;</td>
118
- </tr>
119
- <tr>
120
- <th scope="row">
121
- <?php _e('Credits consumed on','shortpixel-image-optimiser');?>
122
- <?php echo(parse_url(get_site_url(),PHP_URL_HOST));?>:
123
- </th>
124
- <td><strong><?php echo($view->data->fileCount);?></strong></td>
125
- </tr>
126
-
127
- </tbody>
128
- </table>
129
- <div style="display:none">
130
-
131
- </div>
132
- <p style="padding-top: 0px; color: #818181;" ><?php _e('* Saved bandwidth is calculated at 10,000 impressions/image','shortpixel-image-optimiser');?></p>
133
- <p style="padding-top: 0px; color: #818181;" >
134
- <?php printf(__('** Increase your image quota by <a href="https://shortpixel.com/login/%s" target="_blank">upgrading your ShortPixel plan.</a>','shortpixel-image-optimiser'),
135
- $this->hide_api_key ? '' : $view->data->apiKey );?>
136
- </p>
137
- </div>
138
- </section>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
class/view/settings/part-tools.php CHANGED
@@ -11,10 +11,10 @@ $queueRunning = $bulk->isAnyBulkRunning();
11
  ?>
12
 
13
  <section id="tab-tools" class="clearfix <?php echo ($this->display_part == 'tools') ? ' sel-tab ' :''; ?> ">
14
- <h2><a class='tab-link' href='javascript:void(0);' data-id="tab-tools"><?php _e('Tools','shortpixel-image-optimiser');?></a></h2>
15
 
16
 
17
- <p><?php printf(__('The tools provided below are designed to make bulk changes to your image and optimization data. Therefore, it is %s very important %s that you back up your entire website before running them. ', 'shortpixel-image-optimiser'), '<b>', '</b>'); ?></p>
18
 
19
  <div class='wp-shortpixel-options wp-shortpixel-tab-content'>
20
 
@@ -25,34 +25,34 @@ $queueRunning = $bulk->isAnyBulkRunning();
25
  <div class='name'>&nbsp;</div>
26
 
27
  <div class='field action queue-warning'>
28
- <?php _e('It looks like a bulk process is still active. Please note that bulk actions will reset running bulk processes. ', 'shortpixel-image-optimiser'); ?>
29
  </div>
30
  </div>
31
  <?php endif; ?>
32
 
33
 
34
  <div class='option'>
35
- <div class='name'><?php _e('Migrate data', 'shortpixel-image-optimiser'); ?></div>
36
  <div class='field'>
37
  <div class='option-content'>
38
  <div class="spio-inline-help"><span class="dashicons dashicons-editor-help" title="Click for more info" data-link="https://shortpixel.com/knowledge-base/article/539-spio-5-tells-me-to-convert-legacy-data-what-is-this">
39
  </span></div>
40
  <a href="<?php echo esc_url(add_query_arg(array('sp-action' => 'action_debug_redirectBulk', 'bulk' => 'migrate', 'noheader' => true), $url)); ?>" class="button">
41
- <?php _e('Search and Migrate All', 'shortpixel-image-optimiser'); ?>
42
  </a>
43
  </div>
44
- <p class='settings-info'><?php printf(__('ShortPixel Image Optimizer version 5.0 brings a new format for saving the image optimization information. If you have upgraded from a version prior to version 5.0, you may want to convert all your image data to the new format. This conversion will speed up the plugin and ensure that all data is preserved. %s Check your image data after doing the conversion! %s', 'shortpixel-image-optimiser'), '<br><b>', '</b>') ?> </p>
45
  </div>
46
  </div>
47
 
48
 
49
 
50
  <div class='option'>
51
- <div class='name'><?php _e('Clear Queue','shortpixel-image-optimiser'); ?></div>
52
  <div class='field'>
53
 
54
- <a href="<?php echo esc_url(add_query_arg(array('sp-action' => 'action_debug_resetQueue', 'queue' => 'all', 'part' => 'tools'), $url)); ?>" class="button"><?php _e('Clear the Queue','shortpixel-image-optimiser'); ?></a>
55
- <p class='settings-info'><?php _e('Removes all items currently waiting or being processed from all queues. This stops all optimization processes in the entire installation.', 'shortpixel-image-optimiser'); ?> </p>
56
 
57
  </div>
58
  </div>
@@ -62,8 +62,8 @@ $queueRunning = $bulk->isAnyBulkRunning();
62
  <hr />
63
 
64
  <div class='danger-zone'>
65
- <h3><?php _e('Danger Zone - please read carefully!', 'shortpixel-image-optimiser'); ?></h3>
66
- <p><?php printf(__('The following actions are related to cleaning up and uninstalling the plugin. %s They cannot be undone %s. It is important that you create a new backup copy before performing any of these actions, as this may result in data loss.', 'shortpixel-image-optimiser'), '<strong>', '</strong>'); ?></p>
67
  <hr />
68
 
69
 
@@ -75,7 +75,7 @@ $queueRunning = $bulk->isAnyBulkRunning();
75
 
76
  <div class="spio-inline-help"><span class="dashicons dashicons-editor-help" title="Click for more info" data-link="https://shortpixel.com/knowledge-base/article/14-can-i-restore-my-images-what-happens-with-the-originals"></span></div>
77
  </div>
78
- <p class='settings-info'><?php printf(__('%sUndoes%s all optimizations and restores all your backed-up images to their original state. Credits used will not be refunded and you will have to optimize your images again.', 'shortpixel-image-optimiser'), '<b>','</b>'); ?></p>
79
  </div>
80
  </div>
81
 
@@ -84,7 +84,7 @@ $queueRunning = $bulk->isAnyBulkRunning();
84
  <div class='field'>
85
  <a href="<?php echo esc_url(add_query_arg(array('sp-action' => 'action_debug_redirectBulk', 'bulk' => 'removeLegacy', 'noheader' => true), $url)); ?>" class="button danger">Remove Legacy Data</a>
86
 
87
- <p class='settings-info'><?php printf(__('%sRemoves Legacy Data%s (the old format for storing image optimization information in the database, which was used before version 5). This may result in data loss. It is not recommended to do this manually.', 'shortpixel-image-optimiser'), '<b>','</b>'); ?></p>
88
  </div>
89
  </div>
90
 
@@ -93,7 +93,7 @@ $queueRunning = $bulk->isAnyBulkRunning();
93
  <div class='field'>
94
  <div class="option-content">
95
  <button type="button" class='button danger' data-action="open-modal" data-target="ToolsRemoveAll">
96
- <?php _e('Remove all ShortPixel Data', 'shortpixel-image-optimiser'); ?></button>
97
 
98
  <div class="spio-inline-help"><span class="dashicons dashicons-editor-help" title="Click for more info" data-link="https://shortpixel.com/knowledge-base/article/81-remove-all-the-shortpixel-related-data-on-a-wp-website"></span></div>
99
  </div>
@@ -103,16 +103,16 @@ $queueRunning = $bulk->isAnyBulkRunning();
103
  <?php wp_nonce_field('remove-all', 'tools-nonce'); ?>
104
 
105
  <p>&nbsp;</p>
106
- <p><?php _e('This will remove all ShortPixel Data including data about optimization and image backups.', 'shortpixel-image-optimiser'); ?></p>
107
- <?php _e('Type confirm to delete all ShortPixel data', 'shortpixel-image-optimiser'); ?>
108
  <input type="text" name="confirm" value="" data-required='confirm' />
109
 
110
- <p><b><?php _e('I understand that all ShortPixel data will be removed.','shortpixel-image-optimiser'); ?></b></p>
111
 
112
- <button type="button" class='button modal-send' name="uninstall" data-action='ajaxrequest'><?php _e('Remove all data', 'shortpixel-image-optimiser'); ?></button>
113
 
114
  </div> <!-- modal -->
115
- <p class='settings-info'><?php printf(__('%sRemoves all ShortPixel data (including backups) %s and deactivates the plugin. Your images will not be changed (the optimized images will remain), but the next time ShortPixel is activated, it will no longer recognize previous optimizations.', 'shortpixel-image-optimiser'), '<b>','</b>'); ?></p>
116
  </div>
117
  </div>
118
 
@@ -125,7 +125,7 @@ $queueRunning = $bulk->isAnyBulkRunning();
125
 
126
  <div class="option-content">
127
  <button type="button" class='button danger' data-action="open-modal" data-target="ToolsRemoveBackup">
128
- <?php _e('Remove backups', 'shortpixel-image-optimiser'); ?></button>
129
 
130
  <div class="spio-inline-help"><span class="dashicons dashicons-editor-help" title="Click for more info" data-link="https://shortpixel.com/knowledge-base/article/83-how-to-remove-the-backed-up-images-in-wordpress"></span></div>
131
 
@@ -136,19 +136,19 @@ $queueRunning = $bulk->isAnyBulkRunning();
136
  <?php wp_nonce_field('empty-backup', 'tools-nonce'); ?>
137
 
138
  <p>&nbsp;</p>
139
- <p><?php _e('This will delete all the backup images. You won\'t be able to restore from backup or to reoptimize with different settings if you delete the backups.', 'shortpixel-image-optimiser'); ?></p>
140
- <?php _e('Type confirm to delete all ShortPixel backups', 'shortpixel-image-optimiser'); ?>
141
  <input type="text" name="confirm" value="" data-required='confirm' />
142
 
143
- <p><b><?php _e('I understand that all Backups will be removed.','shortpixel-image-optimiser'); ?> </b></p>
144
 
145
  <p class='center'>
146
- <button type="button" class='button modal-send' name="removebackups" data-action='ajaxrequest'><?php _e('Remove backups', 'shortpixel-image-optimiser'); ?></button>
147
  </p>
148
  </div>
149
  </div> <!-- backup modal -->
150
 
151
- <p class='settings-info'><?php _e('When backups are enabled, original images are stored in a backup folder. If you remove the backup folder, you will not be able to restore or reoptimize the images. We strongly recommend that you keep a copy of the backup folder (/wp-content/uploads/ShortpixelBackups/) somewhere safe.','shortpixel-image-optimiser');?>
152
  </div>
153
 
154
  </div>
11
  ?>
12
 
13
  <section id="tab-tools" class="clearfix <?php echo ($this->display_part == 'tools') ? ' sel-tab ' :''; ?> ">
14
+ <h2><a class='tab-link' href='javascript:void(0);' data-id="tab-tools"><?php esc_html_e('Tools','shortpixel-image-optimiser');?></a></h2>
15
 
16
 
17
+ <p><?php printf(esc_html__('The tools provided below are designed to make bulk changes to your image and optimization data. Therefore, it is %s very important %s that you back up your entire website before running them. ', 'shortpixel-image-optimiser'), '<b>', '</b>'); ?></p>
18
 
19
  <div class='wp-shortpixel-options wp-shortpixel-tab-content'>
20
 
25
  <div class='name'>&nbsp;</div>
26
 
27
  <div class='field action queue-warning'>
28
+ <?php esc_html_e('It looks like a bulk process is still active. Please note that bulk actions will reset running bulk processes. ', 'shortpixel-image-optimiser'); ?>
29
  </div>
30
  </div>
31
  <?php endif; ?>
32
 
33
 
34
  <div class='option'>
35
+ <div class='name'><?php esc_html_e('Migrate data', 'shortpixel-image-optimiser'); ?></div>
36
  <div class='field'>
37
  <div class='option-content'>
38
  <div class="spio-inline-help"><span class="dashicons dashicons-editor-help" title="Click for more info" data-link="https://shortpixel.com/knowledge-base/article/539-spio-5-tells-me-to-convert-legacy-data-what-is-this">
39
  </span></div>
40
  <a href="<?php echo esc_url(add_query_arg(array('sp-action' => 'action_debug_redirectBulk', 'bulk' => 'migrate', 'noheader' => true), $url)); ?>" class="button">
41
+ <?php esc_html_e('Search and Migrate All', 'shortpixel-image-optimiser'); ?>
42
  </a>
43
  </div>
44
+ <p class='settings-info'><?php printf(esc_html__('ShortPixel Image Optimizer version 5.0 brings a new format for saving the image optimization information. If you have upgraded from a version prior to version 5.0, you may want to convert all your image data to the new format. This conversion will speed up the plugin and ensure that all data is preserved. %s Check your image data after doing the conversion! %s', 'shortpixel-image-optimiser'), '<br><b>', '</b>') ?> </p>
45
  </div>
46
  </div>
47
 
48
 
49
 
50
  <div class='option'>
51
+ <div class='name'><?php esc_html_e('Clear Queue','shortpixel-image-optimiser'); ?></div>
52
  <div class='field'>
53
 
54
+ <a href="<?php echo esc_url(add_query_arg(array('sp-action' => 'action_debug_resetQueue', 'queue' => 'all', 'part' => 'tools'), $url)); ?>" class="button"><?php esc_html_e('Clear the Queue','shortpixel-image-optimiser'); ?></a>
55
+ <p class='settings-info'><?php esc_html_e('Removes all items currently waiting or being processed from all queues. This stops all optimization processes in the entire installation.', 'shortpixel-image-optimiser'); ?> </p>
56
 
57
  </div>
58
  </div>
62
  <hr />
63
 
64
  <div class='danger-zone'>
65
+ <h3><?php esc_html_e('Danger Zone - please read carefully!', 'shortpixel-image-optimiser'); ?></h3>
66
+ <p><?php printf(esc_html__('The following actions are related to cleaning up and uninstalling the plugin. %s They cannot be undone %s. It is important that you create a new backup copy before performing any of these actions, as this may result in data loss.', 'shortpixel-image-optimiser'), '<strong>', '</strong>'); ?></p>
67
  <hr />
68
 
69
 
75
 
76
  <div class="spio-inline-help"><span class="dashicons dashicons-editor-help" title="Click for more info" data-link="https://shortpixel.com/knowledge-base/article/14-can-i-restore-my-images-what-happens-with-the-originals"></span></div>
77
  </div>
78
+ <p class='settings-info'><?php printf(esc_html__('%sUndoes%s all optimizations and restores all your backed-up images to their original state. Credits used will not be refunded and you will have to optimize your images again.', 'shortpixel-image-optimiser'), '<b>','</b>'); ?></p>
79
  </div>
80
  </div>
81
 
84
  <div class='field'>
85
  <a href="<?php echo esc_url(add_query_arg(array('sp-action' => 'action_debug_redirectBulk', 'bulk' => 'removeLegacy', 'noheader' => true), $url)); ?>" class="button danger">Remove Legacy Data</a>
86
 
87
+ <p class='settings-info'><?php printf(esc_html__('%sRemoves Legacy Data%s (the old format for storing image optimization information in the database, which was used before version 5). This may result in data loss. It is not recommended to do this manually.', 'shortpixel-image-optimiser'), '<b>','</b>'); ?></p>
88
  </div>
89
  </div>
90
 
93
  <div class='field'>
94
  <div class="option-content">
95
  <button type="button" class='button danger' data-action="open-modal" data-target="ToolsRemoveAll">
96
+ <?php esc_html_e('Remove all ShortPixel Data', 'shortpixel-image-optimiser'); ?></button>
97
 
98
  <div class="spio-inline-help"><span class="dashicons dashicons-editor-help" title="Click for more info" data-link="https://shortpixel.com/knowledge-base/article/81-remove-all-the-shortpixel-related-data-on-a-wp-website"></span></div>
99
  </div>
103
  <?php wp_nonce_field('remove-all', 'tools-nonce'); ?>
104
 
105
  <p>&nbsp;</p>
106
+ <p><?php esc_html_e('This will remove all ShortPixel Data including data about optimization and image backups.', 'shortpixel-image-optimiser'); ?></p>
107
+ <?php esc_html_e('Type confirm to delete all ShortPixel data', 'shortpixel-image-optimiser'); ?>
108
  <input type="text" name="confirm" value="" data-required='confirm' />
109
 
110
+ <p><b><?php esc_html_e('I understand that all ShortPixel data will be removed.','shortpixel-image-optimiser'); ?></b></p>
111
 
112
+ <button type="button" class='button modal-send' name="uninstall" data-action='ajaxrequest'><?php esc_html_e('Remove all data', 'shortpixel-image-optimiser'); ?></button>
113
 
114
  </div> <!-- modal -->
115
+ <p class='settings-info'><?php printf(esc_html__('%sRemoves all ShortPixel data (including backups) %s and deactivates the plugin. Your images will not be changed (the optimized images will remain), but the next time ShortPixel is activated, it will no longer recognize previous optimizations.', 'shortpixel-image-optimiser'), '<b>','</b>'); ?></p>
116
  </div>
117
  </div>
118
 
125
 
126
  <div class="option-content">
127
  <button type="button" class='button danger' data-action="open-modal" data-target="ToolsRemoveBackup">
128
+ <?php esc_html_e('Remove backups', 'shortpixel-image-optimiser'); ?></button>
129
 
130
  <div class="spio-inline-help"><span class="dashicons dashicons-editor-help" title="Click for more info" data-link="https://shortpixel.com/knowledge-base/article/83-how-to-remove-the-backed-up-images-in-wordpress"></span></div>
131
 
136
  <?php wp_nonce_field('empty-backup', 'tools-nonce'); ?>
137
 
138
  <p>&nbsp;</p>
139
+ <p><?php esc_html_e('This will delete all the backup images. You won\'t be able to restore from backup or to reoptimize with different settings if you delete the backups.', 'shortpixel-image-optimiser'); ?></p>
140
+ <?php esc_html_e('Type confirm to delete all ShortPixel backups', 'shortpixel-image-optimiser'); ?>
141
  <input type="text" name="confirm" value="" data-required='confirm' />
142
 
143
+ <p><b><?php esc_html_e('I understand that all Backups will be removed.','shortpixel-image-optimiser'); ?> </b></p>
144
 
145
  <p class='center'>
146
+ <button type="button" class='button modal-send' name="removebackups" data-action='ajaxrequest'><?php esc_html_e('Remove backups', 'shortpixel-image-optimiser'); ?></button>
147
  </p>
148
  </div>
149
  </div> <!-- backup modal -->
150
 
151
+ <p class='settings-info'><?php esc_html_e('When backups are enabled, original images are stored in a backup folder. If you remove the backup folder, you will not be able to restore or reoptimize the images. We strongly recommend that you keep a copy of the backup folder (/wp-content/uploads/ShortpixelBackups/) somewhere safe.','shortpixel-image-optimiser');?>
152
  </div>
153
 
154
  </div>
class/view/settings/part-wso.php DELETED
@@ -1,28 +0,0 @@
1
- <?php
2
- namespace ShortPixel;
3
-
4
- $bool = apply_filters('shortpixel/settings/no_banner', true);
5
- if (! $bool )
6
- return;
7
-
8
- if ( defined('SHORTPIXEL_NO_BANNER') && SHORTPIXEL_NO_BANNER == true)
9
- return;
10
-
11
- ?>
12
-
13
- <section class='wso banner'>
14
- <span class="image">
15
- <img src="<?php echo \wpSPIO()->plugin_url() ?>res/img/robo-winky.png" />
16
- </span>
17
- <span class="line"><h3>
18
- <?php printf(__('ARE YOU CONCERNED WITH YOUR %s %s SITE SPEED? %s', 'shortpixel-image-optimiser'),'<br>', '<span class="red">','</span>'); ?>
19
- </h3>
20
- </span>
21
- <span class="line"><h3>
22
- <?php printf(__('ALLOW ShortPixel SPECIALISTS TO %s FIND THE SOLUTION FOR YOU.', 'shortpixel-image-optimiser'), '<br>'); ?>
23
- </h3>
24
- </span>
25
- <span class="button-wrap">
26
- <a href="https://wso.shortpixel.com/?utm_source=SPIO" target="_blank" class='button' ><?php _e('Find out more', 'shortpixel-image-optimiser'); ?></a>
27
- </span>
28
- </section>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
class/view/shortpixel-feedback.php CHANGED
@@ -6,7 +6,7 @@ use ShortPixel\Controller\ApiKeyController as ApiKeyController;
6
  /**
7
  * User: simon
8
  * Date: 11.04.2018
9
- * @todo This whole thing needs redoing.
10
  */
11
  class ShortPixelFeedback {
12
 
@@ -174,12 +174,12 @@ class ShortPixelFeedback {
174
  formContainer = $(formID),
175
  deactivated = true,
176
  detailsStrings = {
177
- 'setup' : '<?php echo __( 'What was the dificult part ?', 'shortpixel-image-optimiser') ?>',
178
- 'docs' : '<?php echo __( 'What can we describe more ?', 'shortpixel-image-optimiser' ) ?>',
179
- 'features' : '<?php echo __( 'How could we improve ?', 'shortpixel-image-optimiser' ) ?>',
180
- 'better-plugin' : '<?php echo __( 'Can you mention it ?', 'shortpixel-image-optimiser' ) ?>',
181
- 'incompatibility' : '<?php echo __( 'With what plugin or theme is incompatible ?', 'shortpixel-image-optimiser' ) ?>',
182
- 'maintenance' : '<?php echo __( 'Please specify', 'shortpixel-image-optimiser') ?>',
183
  'temporary' : '',
184
  };
185
 
@@ -188,7 +188,7 @@ class ShortPixelFeedback {
188
 
189
  var SubmitFeedback = function(data, formContainer){
190
  data['action'] = 'shortpixel_deactivate_plugin';
191
- data['security'] = '<?php echo wp_create_nonce("shortpixel_deactivate_plugin" ); ?>';
192
  data['dataType'] = 'json';
193
  data['keep-settings'] = formContainer.find('#shortpixel-keep-settings:checked').length;
194
 
@@ -328,8 +328,8 @@ class ShortPixelFeedback {
328
  $anonymous = (intval($_POST['anonymous']) == 1) ? true : false;
329
  $args = array(
330
  'key' => $this->key,
331
- 'reason' => sanitize_text_field($_POST['reason']),
332
- 'details' => sanitize_text_field($_POST['details']),
333
  'anonymous' => $anonymous
334
  );
335
  $request = new ShortPixelPluginRequest( $this->plugin_file, 'http://' . SHORTPIXEL_API . '/v2/feedback.php', $args );
6
  /**
7
  * User: simon
8
  * Date: 11.04.2018
9
+ * @todo This whole thing needs redoing.
10
  */
11
  class ShortPixelFeedback {
12
 
174
  formContainer = $(formID),
175
  deactivated = true,
176
  detailsStrings = {
177
+ 'setup' : '<?php esc_html_e( 'What was the dificult part ?', 'shortpixel-image-optimiser') ?>',
178
+ 'docs' : '<?php esc_html_e( 'What can we describe more ?', 'shortpixel-image-optimiser' ) ?>',
179
+ 'features' : '<?php esc_html_e( 'How could we improve ?', 'shortpixel-image-optimiser' ) ?>',
180
+ 'better-plugin' : '<?php esc_html_e( 'Can you mention it ?', 'shortpixel-image-optimiser' ) ?>',
181
+ 'incompatibility' : '<?php esc_html_e( 'With what plugin or theme is incompatible ?', 'shortpixel-image-optimiser' ) ?>',
182
+ 'maintenance' : '<?php esc_html_e( 'Please specify', 'shortpixel-image-optimiser') ?>',
183
  'temporary' : '',
184
  };
185
 
188
 
189
  var SubmitFeedback = function(data, formContainer){
190
  data['action'] = 'shortpixel_deactivate_plugin';
191
+ data['security'] = '<?php echo sanitize_key(wp_create_nonce("shortpixel_deactivate_plugin" )); ?>';
192
  data['dataType'] = 'json';
193
  data['keep-settings'] = formContainer.find('#shortpixel-keep-settings:checked').length;
194
 
328
  $anonymous = (intval($_POST['anonymous']) == 1) ? true : false;
329
  $args = array(
330
  'key' => $this->key,
331
+ 'reason' => sanitize_text_field(wp_unslash($_POST['reason'])),
332
+ 'details' => sanitize_text_field(wp_unslash($_POST['details'])),
333
  'anonymous' => $anonymous
334
  );
335
  $request = new ShortPixelPluginRequest( $this->plugin_file, 'http://' . SHORTPIXEL_API . '/v2/feedback.php', $args );
class/view/shortpixel-plugin-request.php CHANGED
@@ -6,7 +6,7 @@ use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
6
  * User: simon
7
  * Date: 11.04.2018
8
  */
9
- // @todo Remove File if no crashes
10
  class ShortPixelPluginRequest {
11
 
12
  /**
@@ -95,7 +95,7 @@ class ShortPixelPluginRequest {
95
  *
96
  */
97
  private function _collect_server_data() {
98
- $this->data['server']['server'] = isset( $_SERVER['SERVER_SOFTWARE'] ) ? sanitize_text_field($_SERVER['SERVER_SOFTWARE']) : '';
99
  $this->data['server']['php_version'] = phpversion();
100
  $this->data['server']['url'] = esc_url(home_url());
101
  }
6
  * User: simon
7
  * Date: 11.04.2018
8
  */
9
+ // @todo This is used by feedback. Should be replaced a some point.
10
  class ShortPixelPluginRequest {
11
 
12
  /**
95
  *
96
  */
97
  private function _collect_server_data() {
98
+ $this->data['server']['server'] = isset( $_SERVER['SERVER_SOFTWARE'] ) ? sanitize_text_field(wp_unslash($_SERVER['SERVER_SOFTWARE'])) : '';
99
  $this->data['server']['php_version'] = phpversion();
100
  $this->data['server']['url'] = esc_url(home_url());
101
  }
class/view/snippets/part-comparer.php CHANGED
@@ -9,7 +9,7 @@ namespace ShortPixel;
9
  <div id="spUploadCompare" class="shortpixel-modal shortpixel-hide">
10
  <div class="sp-modal-title">
11
  <button type="button" class="sp-close-button">&times;</button>
12
- <?php _e('Compare Images', 'shortpixel-image-optimiser');?>
13
  </div>
14
  <div class="sp-modal-body sptw-modal-spinner" style="height:400px;padding:0;">
15
  <div class="shortpixel-slider" style="z-index:2000;">
9
  <div id="spUploadCompare" class="shortpixel-modal shortpixel-hide">
10
  <div class="sp-modal-title">
11
  <button type="button" class="sp-close-button">&times;</button>
12
+ <?php esc_html_e('Compare Images', 'shortpixel-image-optimiser');?>
13
  </div>
14
  <div class="sp-modal-body sptw-modal-spinner" style="height:400px;padding:0;">
15
  <div class="shortpixel-slider" style="z-index:2000;">
class/view/snippets/part-inline-help.php CHANGED
@@ -1,3 +1,7 @@
 
 
 
 
1
 
2
  <div id="spioHelpShade" class="spio-modal-shade" style="display:none;">
3
  <div id="spioHelp" class="spio-modal spio-hide" style="min-width:610px;margin-left:-305px;">
1
+ <?php
2
+ namespace ShortPixel;
3
+
4
+ ?>
5
 
6
  <div id="spioHelpShade" class="spio-modal-shade" style="display:none;">
7
  <div id="spioHelp" class="spio-modal spio-hide" style="min-width:610px;margin-left:-305px;">
class/view/snippets/part-inline-modal.php CHANGED
@@ -1,3 +1,7 @@
 
 
 
 
1
 
2
  <div id="spioSettingsModalShade" class="spio-modal-shade" style="display:none;"></div>
3
  <div id="spioSettingsModal" class="spio-modal spio-hide" style="min-width:610px;margin-left:-305px;">
1
+ <?php
2
+ namespace ShortPixel;
3
+
4
+ ?>
5
 
6
  <div id="spioSettingsModalShade" class="spio-modal-shade" style="display:none;"></div>
7
  <div id="spioSettingsModal" class="spio-modal spio-hide" style="min-width:610px;margin-left:-305px;">
class/view/snippets/part-svgloader.php CHANGED
@@ -1,3 +1,8 @@
 
 
 
 
 
1
  <svg version="1.1" class="svg-loader" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
2
  viewBox="0 0 100 50" enable-background="new 0 0 0 0" xml:space="preserve">
3
  <circle fill="#1cbecb" stroke="none" cx="6" cy="25" r="6">
1
+ <?php
2
+ namespace ShortPixel;
3
+
4
+ ?>
5
+
6
  <svg version="1.1" class="svg-loader" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
7
  viewBox="0 0 100 50" enable-background="new 0 0 0 0" xml:space="preserve">
8
  <circle fill="#1cbecb" stroke="none" cx="6" cy="25" r="6">
class/view/view-bulk.php CHANGED
@@ -4,20 +4,19 @@ namespace ShortPixel;
4
 
5
 
6
  <div class="shortpixel-bulk-wrapper">
7
- <h1><?php _e('ShortPixel Bulk Processing', 'shortpixel-image-optimiser'); ?></h1>
8
 
9
- <div id="processPaused" class="processor-paused" data-action="ResumeBulk"><span class='dashicons dashicons-controls-pause' data-action="ResumeBulk"></span>The Bulk Processing is paused, please click to resume</div>
 
10
 
11
  <div id="processorOverQuota" class="processor-overquota">
12
- <h3>There are no credits left. The Bulk Processing is paused.</h3>
13
- <p><a href="javascript:window.location.reload()">Click to reload page after adding credits</a></p>
14
  </div>
15
 
16
-
17
  <div class="screen-wrapper">
18
 
19
  <?php
20
- //$this->loadView('bulk/part-progressbar', false);
21
  $this->loadview('bulk/part-dashboard');
22
  $this->loadView('bulk/part-selection');
23
  $this->loadView('bulk/part-summary');
@@ -26,10 +25,7 @@ namespace ShortPixel;
26
 
27
  $this->loadView('bulk/part-bulk-special');
28
 
29
- //$this->loadView('bulk/part-results');
30
-
31
  if (\wpSPIO()->env()->is_debug)
32
- // $this->loadView('bulk/part-debug');
33
  ?>
34
 
35
  </div>
4
 
5
 
6
  <div class="shortpixel-bulk-wrapper">
7
+ <h1><?php esc_html_e('ShortPixel Bulk Processing', 'shortpixel-image-optimiser'); ?></h1>
8
 
9
+ <div id="processPaused" class="processor-paused" data-action="ResumeBulk"><span class='dashicons dashicons-controls-pause' data-action="ResumeBulk"></span>
10
+ <?php esc_html_e('The Bulk Processing is paused, please click to resume','shortpixel-image-optimiser'); ?></div>
11
 
12
  <div id="processorOverQuota" class="processor-overquota">
13
+ <h3><?php esc_html_e('There are no credits left. The Bulk Processing is paused.','shortpixel-image-optimiser'); ?></h3>
14
+ <p><a href="javascript:window.location.reload()"><?php esc_html_e('Click to reload page after adding credits','shortpixel-image-optimiser'); ?></a></p>
15
  </div>
16
 
 
17
  <div class="screen-wrapper">
18
 
19
  <?php
 
20
  $this->loadview('bulk/part-dashboard');
21
  $this->loadView('bulk/part-selection');
22
  $this->loadView('bulk/part-summary');
25
 
26
  $this->loadView('bulk/part-bulk-special');
27
 
 
 
28
  if (\wpSPIO()->env()->is_debug)
 
29
  ?>
30
 
31
  </div>
class/view/view-edit-media.php CHANGED
@@ -5,14 +5,14 @@ use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
5
 
6
  ?>
7
 
8
- <div id='sp-msg-<?php echo($view->id);?>' class='column-wp-shortPixel view-edit-media'>
9
  <?php // Debug Data
10
  if (! is_null($view->debugInfo) && is_array($view->debugInfo) && count($view->debugInfo) > 0 ): ?>
11
  <div class='debugInfo' id='debugInfo'>
12
- <a class='debugModal' data-modal="debugInfo" ><?php _e('Debug Window', 'shortpixel-image-optimiser') ?></a>
13
  <div class='content wrapper'>
14
  <?php foreach($view->debugInfo as $index => $item): ?>
15
- <ul class="debug-<?php echo $index ?>">
16
  <li><strong><?php echo $item[0]; ?></strong>
17
  <?php
18
  if (is_array($item[1]) || is_object($item[1]))
@@ -24,7 +24,6 @@ if (! is_null($view->debugInfo) && is_array($view->debugInfo) && count($view->de
24
  </ul>
25
  <?php endforeach; ?>
26
  <p>&nbsp;</p>
27
- <p>&nbsp;</p>
28
  </div>
29
  </div>
30
  <?php endif; ?>
@@ -48,14 +47,13 @@ if (! is_null($view->debugInfo) && is_array($view->debugInfo) && count($view->de
48
  $link = ($action['type'] == 'js') ? 'javascript:' . $action['function'] : $action['function'];
49
 
50
  ?>
51
- <a href="<?php echo $link ?>" class="<?php echo $classes ?>"><?php echo $action['text'] ?></a>
52
 
53
  <?php
54
  endforeach;
55
 
56
  endif;
57
 
58
-
59
  ?>
60
 
61
  <?php if (property_exists($view, 'stats') && count($view->stats) > 0): ?>
@@ -69,14 +67,12 @@ if (! is_null($view->debugInfo) && is_array($view->debugInfo) && count($view->de
69
  </div>
70
  </div>
71
 
72
- <div id="sp-message-<?php echo($this->view->id); ?>" class='messages'>
73
  <?php if (! is_null($view->status_message)): ?>
74
- <?php echo $view->status_message; ?>
75
  <?php endif; ?>
76
  </div>
77
 
78
  <div id='shortpixel-errorbox' class="errorbox">&nbsp;</div>
79
 
80
-
81
-
82
  <?php $this->loadView('snippets/part-comparer'); ?>
5
 
6
  ?>
7
 
8
+ <div id='sp-msg-<?php echo( esc_attr($view->id) );?>' class='column-wp-shortPixel view-edit-media'>
9
  <?php // Debug Data
10
  if (! is_null($view->debugInfo) && is_array($view->debugInfo) && count($view->debugInfo) > 0 ): ?>
11
  <div class='debugInfo' id='debugInfo'>
12
+ <a class='debugModal' data-modal="debugInfo" ><?php esc_html_e('Debug Window', 'shortpixel-image-optimiser') ?></a>
13
  <div class='content wrapper'>
14
  <?php foreach($view->debugInfo as $index => $item): ?>
15
+ <ul class="debug-<?php echo esc_attr($index) ?>">
16
  <li><strong><?php echo $item[0]; ?></strong>
17
  <?php
18
  if (is_array($item[1]) || is_object($item[1]))
24
  </ul>
25
  <?php endforeach; ?>
26
  <p>&nbsp;</p>
 
27
  </div>
28
  </div>
29
  <?php endif; ?>
47
  $link = ($action['type'] == 'js') ? 'javascript:' . $action['function'] : $action['function'];
48
 
49
  ?>
50
+ <a href="<?php echo $link ?>" class="<?php echo esc_attr($classes) ?>"><?php echo esc_html($action['text']) ?></a>
51
 
52
  <?php
53
  endforeach;
54
 
55
  endif;
56
 
 
57
  ?>
58
 
59
  <?php if (property_exists($view, 'stats') && count($view->stats) > 0): ?>
67
  </div>
68
  </div>
69
 
70
+ <div id="sp-message-<?php echo( esc_attr($this->view->id) ); ?>" class='messages'>
71
  <?php if (! is_null($view->status_message)): ?>
72
+ <?php echo esc_html($view->status_message); ?>
73
  <?php endif; ?>
74
  </div>
75
 
76
  <div id='shortpixel-errorbox' class="errorbox">&nbsp;</div>
77
 
 
 
78
  <?php $this->loadView('snippets/part-comparer'); ?>
class/view/view-list-media.php CHANGED
@@ -2,10 +2,8 @@
2
  namespace ShortPixel;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
 
5
-
6
-
7
  ?>
8
- <div class='sp-column-info' id='sp-msg-<?php echo($this->view->mediaItem->get('id') );?>'>
9
  <?php if (property_exists($this->view,'text') && strlen($this->view->text) > 0): ?>
10
  <p><?php echo $this->view->text; ?></p>
11
  <?php endif;
@@ -14,9 +12,12 @@ if (isset($this->view->actions)):
14
  foreach($this->view->actions as $actionName => $action):
15
  $classes = ($action['display'] == 'button') ? " button-smaller button-primary $actionName " : "$actionName";
16
  $link = ($action['type'] == 'js') ? 'javascript:' . $action['function'] : $action['function'];
 
 
17
 
18
  ?>
19
- <a href="<?php echo $link ?>" class="<?php echo $classes ?>"><?php echo $action['text'] ?></a>
 
20
 
21
  <?php
22
  endforeach;
@@ -31,6 +32,3 @@ if (isset($this->view->list_actions))
31
  }
32
  ?>
33
  </div>
34
-
35
-
36
- <?php //$this->loadView('snippets/part-comparer'); ?>
2
  namespace ShortPixel;
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
 
 
 
5
  ?>
6
+ <div class='sp-column-info' id='sp-msg-<?php echo esc_attr($this->view->mediaItem->get('id') );?>'>
7
  <?php if (property_exists($this->view,'text') && strlen($this->view->text) > 0): ?>
8
  <p><?php echo $this->view->text; ?></p>
9
  <?php endif;
12
  foreach($this->view->actions as $actionName => $action):
13
  $classes = ($action['display'] == 'button') ? " button-smaller button-primary $actionName " : "$actionName";
14
  $link = ($action['type'] == 'js') ? 'javascript:' . $action['function'] : $action['function'];
15
+ $newtab = ($actionName == 'extendquota') ? 'target="_blank"' : '';
16
+
17
 
18
  ?>
19
+ <a href="<?php echo $link ?>" <?php echo esc_attr($newtab); ?> class="<?php echo $classes ?>"><?php echo $action['text'] ?></a>
20
+
21
 
22
  <?php
23
  endforeach;
32
  }
33
  ?>
34
  </div>
 
 
 
class/view/view-other-media.php CHANGED
@@ -8,6 +8,7 @@ use ShortPixel\Helper\UiHelper as UiHelper;
8
 
9
  $fs = \wpSPIO()->filesystem();
10
 
 
11
  if ( isset($_GET['noheader']) ) {
12
  require_once(ABSPATH . 'wp-admin/admin-header.php');
13
  }
@@ -16,7 +17,7 @@ if ( isset($_GET['noheader']) ) {
16
  ?>
17
  <div class="wrap shortpixel-other-media">
18
  <h2>
19
- <?php _e('Custom Media optimized by ShortPixel','shortpixel-image-optimiser');?>
20
  </h2>
21
 
22
  <div class='toolbar'>
@@ -24,8 +25,8 @@ if ( isset($_GET['noheader']) ) {
24
  <?php
25
  $nonce = wp_create_nonce( 'refresh_folders' );
26
  ?>
27
- <a href="<?php echo admin_url('upload.php?page=wp-short-pixel-custom&sp-action=action_refreshfolders&_wpnonce=' . $nonce); ?>" id="refresh" class="button button-primary" title="<?php _e('Refresh custom folders content','shortpixel-image-optimiser');?>">
28
- <?php _e('Refresh folders','shortpixel-image-optimiser');?>
29
  </a>
30
  </div>
31
  <hr class='wp-header-end' />
@@ -33,16 +34,15 @@ if ( isset($_GET['noheader']) ) {
33
  <div class="searchbox">
34
  <form method="get">
35
  <input type="hidden" name="page" value="wp-short-pixel-custom" />
36
- <input type='hidden' name='order' value="<?php echo $this->order ?>" />
37
- <input type="hidden" name="orderby" value="<?php echo $this->orderby ?>" />
38
 
39
  <p class="search-form">
40
- <label><?php _e('Search', 'shortpixel-image-optimiser'); ?></label>
41
- <input type="text" name="s" value="<?php echo $this->search ?>" />
42
 
43
  </p>
44
- <?php //$customMediaListTable->search_box("Search", "sp_search_file");
45
- ?>
46
  </form>
47
  </div>
48
  </div>
@@ -54,11 +54,11 @@ if ( isset($_GET['noheader']) ) {
54
 
55
  if ($this->show_hidden)
56
  {
57
- printf('<a href="%s">%s</a>', esc_url(add_query_arg('show_hidden',false)), __('Back to normal items', 'shortpixel-image-optimiser'));
58
  }
59
  else
60
  {
61
- printf('<a href="%s">%s</a>', esc_url(add_query_arg('show_hidden',true)), __('Show hidden items', 'shortpixel-image-optimiser'));
62
  }
63
 
64
  endif; ?>
@@ -74,7 +74,7 @@ if ( isset($_GET['noheader']) ) {
74
  <?php foreach($this->view->headings as $hname => $heading):
75
  $isSortable = $heading['sortable'];
76
  ?>
77
- <span class='heading <?php echo $hname ?>'>
78
  <?php echo $this->getDisplayHeading($heading); ?>
79
  </span>
80
 
@@ -85,9 +85,9 @@ if ( isset($_GET['noheader']) ) {
85
  <div class='no-items'> <p>
86
  <?php
87
  if ($this->search === false):
88
- echo(__('No images available. Go to <a href="options-general.php?page=wp-shortpixel-settings&part=adv-settings">Advanced Settings</a> to configure additional folders to be optimized.','shortpixel-image-optimiser'));
89
  else:
90
- echo __('Your search query didn\'t result in any images. ', 'shortpixel-image-optimiser');
91
  endif; ?>
92
  </p>
93
  </div>
@@ -102,7 +102,7 @@ if ( isset($_GET['noheader']) ) {
102
 
103
  ?>
104
 
105
- <div class='item item-<?php echo $item->get('id') ?>'>
106
  <?php
107
  // $itemFile = $fs->getFile($item->path);
108
  $filesize = $item->getFileSize();
@@ -118,14 +118,15 @@ if ( isset($_GET['noheader']) ) {
118
  $is_heavy = ($filesize >= 500000 && $filesize > 0);
119
 
120
  ?>
121
- <span><a href="<?php echo($img_url);?>" target="_blank">
122
  <div class='thumb' <?php if($is_heavy)
123
  {
124
- echo('title="' . __('This image is heavy and it would slow this page down if displayed here. Click to open it in a new browser tab.', 'shortpixel-image-optimiser') . '"');
125
  }
126
- ?> style="background-image:url('<?php echo($is_heavy ? wpSPIO()->plugin_url('res/img/heavy-image@2x.png') : $img_url) ?>')"></div>
 
127
  </a></span>
128
- <span class='filename'><?php echo $item->getFileName() ?>
129
  <div class="row-actions"><?php
130
  $numberActions = count($rowActions);
131
  for ($i = 0; $i < $numberActions; $i++)
@@ -135,12 +136,12 @@ if ( isset($_GET['noheader']) ) {
135
  echo '|';
136
  }
137
  ?>
138
- <span class='item-id'>#<?php echo $item->get('id'); ?></span>
139
  </div>
140
  </span>
141
- <span class='folderpath'><?php echo (string) $item->getFileDir(); ?></span>
142
- <span class='mediatype'><?php echo $media_type ?></span>
143
- <span class="date"><?php echo $display_date ?></span>
144
 
145
  <span >
146
  <?php $this->doActionColumn($item); ?>
8
 
9
  $fs = \wpSPIO()->filesystem();
10
 
11
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is not a form
12
  if ( isset($_GET['noheader']) ) {
13
  require_once(ABSPATH . 'wp-admin/admin-header.php');
14
  }
17
  ?>
18
  <div class="wrap shortpixel-other-media">
19
  <h2>
20
+ <?php esc_html_e('Custom Media optimized by ShortPixel','shortpixel-image-optimiser');?>
21
  </h2>
22
 
23
  <div class='toolbar'>
25
  <?php
26
  $nonce = wp_create_nonce( 'refresh_folders' );
27
  ?>
28
+ <a href="<?php echo esc_url(admin_url('upload.php?page=wp-short-pixel-custom&sp-action=action_refreshfolders&_wpnonce=' . $nonce)); ?>" id="refresh" class="button button-primary" title="<?php esc_attr_e('Refresh custom folders content','shortpixel-image-optimiser');?>">
29
+ <?php esc_attr_e('Refresh folders','shortpixel-image-optimiser');?>
30
  </a>
31
  </div>
32
  <hr class='wp-header-end' />
34
  <div class="searchbox">
35
  <form method="get">
36
  <input type="hidden" name="page" value="wp-short-pixel-custom" />
37
+ <input type='hidden' name='order' value="<?php echo esc_attr($this->order) ?>" />
38
+ <input type="hidden" name="orderby" value="<?php echo esc_attr($this->orderby) ?>" />
39
 
40
  <p class="search-form">
41
+ <label><?php esc_html_e('Search', 'shortpixel-image-optimiser'); ?></label>
42
+ <input type="text" name="s" value="<?php echo esc_attr($this->search) ?>" />
43
 
44
  </p>
45
+
 
46
  </form>
47
  </div>
48
  </div>
54
 
55
  if ($this->show_hidden)
56
  {
57
+ printf('<a href="%s">%s</a>', esc_url(add_query_arg('show_hidden',false)), esc_html__('Back to normal items', 'shortpixel-image-optimiser'));
58
  }
59
  else
60
  {
61
+ printf('<a href="%s">%s</a>', esc_url(add_query_arg('show_hidden',true)), esc_html__('Show hidden items', 'shortpixel-image-optimiser'));
62
  }
63
 
64
  endif; ?>
74
  <?php foreach($this->view->headings as $hname => $heading):
75
  $isSortable = $heading['sortable'];
76
  ?>
77
+ <span class='heading <?php echo esc_attr($hname) ?>'>
78
  <?php echo $this->getDisplayHeading($heading); ?>
79
  </span>
80
 
85
  <div class='no-items'> <p>
86
  <?php
87
  if ($this->search === false):
88
+ printf(esc_html__('No images available. Go to %s Advanced Settings %s to configure additional folders to be optimized.','shortpixel-image-optimiser'), '<a href="options-general.php?page=wp-shortpixel-settings&part=adv-settings">', '</a>');
89
  else:
90
+ echo esc_html__('Your search query didn\'t result in any images. ', 'shortpixel-image-optimiser');
91
  endif; ?>
92
  </p>
93
  </div>
102
 
103
  ?>
104
 
105
+ <div class='item item-<?php echo esc_attr($item->get('id')) ?>'>
106
  <?php
107
  // $itemFile = $fs->getFile($item->path);
108
  $filesize = $item->getFileSize();
118
  $is_heavy = ($filesize >= 500000 && $filesize > 0);
119
 
120
  ?>
121
+ <span><a href="<?php echo esc_attr($img_url); ?>" target="_blank">
122
  <div class='thumb' <?php if($is_heavy)
123
  {
124
+ echo('title="' . esc_attr__('This image is heavy and it would slow this page down if displayed here. Click to open it in a new browser tab.', 'shortpixel-image-optimiser') . '"');
125
  }
126
+ ?> style="background-image:url('<?php echo($is_heavy ? esc_url(wpSPIO()->plugin_url('res/img/heavy-image@2x.png')) : esc_url($img_url)) ?>')">
127
+ </div>
128
  </a></span>
129
+ <span class='filename'><?php echo esc_html($item->getFileName()) ?>
130
  <div class="row-actions"><?php
131
  $numberActions = count($rowActions);
132
  for ($i = 0; $i < $numberActions; $i++)
136
  echo '|';
137
  }
138
  ?>
139
+ <span class='item-id'>#<?php echo esc_attr($item->get('id')); ?></span>
140
  </div>
141
  </span>
142
+ <span class='folderpath'><?php echo esc_html( (string) $item->getFileDir()); ?></span>
143
+ <span class='mediatype'><?php echo esc_html($media_type) ?></span>
144
+ <span class="date"><?php echo esc_html($display_date) ?></span>
145
 
146
  <span >
147
  <?php $this->doActionColumn($item); ?>
class/view/view-restore-all.php DELETED
@@ -1,53 +0,0 @@
1
-
2
- <div class="wrap short-pixel-bulk-page bulk-restore-all">
3
- <form action='<?php echo esc_url(remove_query_arg('part')); ?>' method='POST' >
4
- <?php wp_nonce_field('sp-bulk', 'sp-nonce'); ?>
5
- <h1><?php _e('Bulk Image Optimization by ShortPixel','shortpixel-image-optimiser');?></h1>
6
-
7
- <div class="sp-notice sp-notice-info sp-floating-block sp-full-width">
8
-
9
- <h3><?php _e( "Are you sure you want to restore from backup all the images optimized with ShortPixel?", 'shortpixel-image-optimiser' ); ?></h3>
10
-
11
- <p><?php _e('Please read carefully. This function will: ', 'shortpixel-image-optimiser'); ?> </p>
12
- <ol>
13
- <li><?php _e('Remove all optimized images from media library', 'shortpixel-image-optimiser'); ?></li>
14
- <li><?php _e( sprintf('Remove all optimized images from %s selected %s other media', '<strong>', '</strong>'), 'shortpixel-image-optimiser'); ?></li>
15
- </ol>
16
-
17
- <section class='select_folders'>
18
- <h4><?php _e('Select which Custom Media Folders to restore', 'shortpixel-image-optimiser'); ?></h4>
19
-
20
- <?php $folders = $controller->getCustomFolders();
21
- // echo get_class($controller);
22
- foreach($folders as $folder):
23
-
24
- $path = $folder->getPath();
25
- $fileCount = $folder->getFileCount();
26
- $folder_id = $folder->getId();
27
- // $status = $folder->getStatus();
28
- ?>
29
-
30
-
31
- <label class='input'><input type='checkbox' name='selected_folders[]' value='<?php echo $folder_id ?>' checked /> <?php echo $path ?> <span class='filecount'> (<?php printf ('%s File(s)', $fileCount) ?>) </span></label>
32
- <?php endforeach; ?>
33
- </section>
34
-
35
- <section class='random_check'>
36
- <div><?php _e('To continue and agree with the warning, please check the correct value below', 'shortpixel-image-optimiser') ?>
37
- <div class='random_answer'><?php echo $controller->randomAnswer(); ?></div>
38
- </div>
39
-
40
- <div class='inputs'><?php echo $controller->randomCheck(); ?></div>
41
- </section>
42
-
43
- <div class='form-controls'>
44
- <a class='button' href="<?php echo esc_url(remove_query_arg('part')) ?>"><?php _e('Back', 'shortpixel-image-optimiser'); ?></a>
45
- <button disabled aria-disabled="true" type='submit' class='button bulk restore disabled' name='bulkRestore' id='bulkRestore'><?php _e('Bulk Restore', 'shortpixel-image-optimiser'); ?></button>
46
- </div>
47
-
48
- <div class='error'><p><?php _e('It is strongly recommended to backup your uploads', 'shortpixel-image-optimiser'); ?></p>
49
- </div>
50
-
51
- </div> <!-- sp-notice -->
52
- </form>
53
- </div> <!-- wrap -->
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
class/view/view-settings.php CHANGED
@@ -5,19 +5,19 @@ use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
5
 
6
  ?>
7
  <div class="wrap is-shortpixel-settings-page">
8
- <h1><?php _e('ShortPixel Plugin Settings','shortpixel-image-optimiser');?></h1>
9
  <div class='top-menu'>
10
 
11
  <div class='links'>
12
  <a href="https://shortpixel.com/<?php
13
- echo(($view->data->apiKey ? "login/". $view->data->apiKey : "pricing"));
14
- ?>" target="_blank"><?php _e( 'Buy credits', 'shortpixel-image-optimiser' );?></a> |
15
- <a href="https://shortpixel.com/knowledge-base/" target="_blank"><?php _e('Knowledge Base','shortpixel-image-optimiser');?></a> |
16
- <a href="https://shortpixel.com/contact" target="_blank"><?php _e('Contact Support','shortpixel-image-optimiser');?></a> |
17
  <a href="https://shortpixel.com/<?php
18
- echo(($view->data->apiKey ? "login/". $view->data->apiKey . "/dashboard" : "login"));
19
  ?>" target="_blank">
20
- <?php _e('ShortPixel account','shortpixel-image-optimiser');?>
21
  </a>
22
  <div class='pie-wrapper'><?php $this->loadView('settings/part-optpie'); ?></div>
23
  </div>
@@ -26,9 +26,9 @@ use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
26
  <?php if (! is_null($this->quotaData)): ?>
27
  <div class='quota-remaining'>
28
  <a href="https://shortpixel.com/<?php
29
- echo(($view->data->apiKey ? "login/". $view->data->apiKey . "/dashboard" : "login"));
30
  ?>" target="_blank">
31
- <?php printf(__('%s Credits remaining', 'shortpixel-image-optimiser'), $this->formatNumber($this->quotaData->total->remaining, 0)); ?>
32
  </a>
33
  </div>
34
  <?php endif; ?>
@@ -45,13 +45,10 @@ use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
45
 
46
  <?php
47
  if ($this->is_verifiedkey):
48
-
49
-
50
-
51
  ?>
52
  <div class='section-wrapper'>
53
  <form name='wp_shortpixel_options' action='<?php echo esc_url(add_query_arg('noheader', 'true')) ?>' method='post' id='wp_shortpixel_options'>
54
- <input type='hidden' name='display_part' value="<?php echo $this->display_part ?>" />
55
  <?php wp_nonce_field($this->form_action, 'sp-nonce'); ?>
56
 
57
  <?php
5
 
6
  ?>
7
  <div class="wrap is-shortpixel-settings-page">
8
+ <h1><?php esc_html_e('ShortPixel Plugin Settings','shortpixel-image-optimiser');?></h1>
9
  <div class='top-menu'>
10
 
11
  <div class='links'>
12
  <a href="https://shortpixel.com/<?php
13
+ echo esc_attr(($view->data->apiKey ? "login/". $view->data->apiKey : "pricing"));
14
+ ?>" target="_blank"><?php esc_html_e( 'Buy credits', 'shortpixel-image-optimiser' );?></a> |
15
+ <a href="https://shortpixel.com/knowledge-base/" target="_blank"><?php esc_html_e('Knowledge Base','shortpixel-image-optimiser');?></a> |
16
+ <a href="https://shortpixel.com/contact" target="_blank"><?php esc_html_e('Contact Support','shortpixel-image-optimiser');?></a> |
17
  <a href="https://shortpixel.com/<?php
18
+ echo esc_attr(($view->data->apiKey ? "login/". $view->data->apiKey . "/dashboard" : "login"));
19
  ?>" target="_blank">
20
+ <?php esc_html_e('ShortPixel account','shortpixel-image-optimiser');?>
21
  </a>
22
  <div class='pie-wrapper'><?php $this->loadView('settings/part-optpie'); ?></div>
23
  </div>
26
  <?php if (! is_null($this->quotaData)): ?>
27
  <div class='quota-remaining'>
28
  <a href="https://shortpixel.com/<?php
29
+ echo esc_attr(($view->data->apiKey ? "login/". $view->data->apiKey . "/dashboard" : "login"));
30
  ?>" target="_blank">
31
+ <?php printf(esc_html__('%s Credits remaining', 'shortpixel-image-optimiser'), esc_html($this->formatNumber($this->quotaData->total->remaining, 0))); ?>
32
  </a>
33
  </div>
34
  <?php endif; ?>
45
 
46
  <?php
47
  if ($this->is_verifiedkey):
 
 
 
48
  ?>
49
  <div class='section-wrapper'>
50
  <form name='wp_shortpixel_options' action='<?php echo esc_url(add_query_arg('noheader', 'true')) ?>' method='post' id='wp_shortpixel_options'>
51
+ <input type='hidden' name='display_part' value="<?php echo esc_attr($this->display_part) ?>" />
52
  <?php wp_nonce_field($this->form_action, 'sp-nonce'); ?>
53
 
54
  <?php
class/wp-shortpixel-settings.php CHANGED
@@ -45,7 +45,7 @@ class WPShortPixelSettings extends \ShortPixel\Model {
45
  'excludePatterns' => array('key' => 'wp-short-pixel-exclude-patterns', 'default' => array(), 'group' => 'options'),
46
  'png2jpg' => array('key' => 'wp-short-pixel-png2jpg', 'default' => 0, 'group' => 'options'),
47
  'excludeSizes' => array('key' => 'wp-short-pixel-excludeSizes', 'default' => array(), 'group' => 'options'),
48
- 'currentVersion' => array('key' => 'wp-short-pixel-currentVersion', 'default' => null, 'group' => 'options'),
49
 
50
  //CloudFlare
51
  'cloudflareEmail' => array( 'key' => 'wp-short-pixel-cloudflareAPIEmail', 'default' => '', 'group' => 'options'),
@@ -225,9 +225,9 @@ class WPShortPixelSettings extends \ShortPixel\Model {
225
  }
226
  $trace = debug_backtrace();
227
  trigger_error(
228
- 'Undefined property via __get(): ' . $name .
229
- ' in ' . $trace[0]['file'] .
230
- ' on line ' . $trace[0]['line'],
231
  E_USER_NOTICE);
232
  return null;
233
  }
@@ -309,33 +309,4 @@ class WPShortPixelSettings extends \ShortPixel\Model {
309
  }
310
  }
311
 
312
- public function ajax_helpscoutOptin()
313
- {
314
- $toggle = isset($_POST['toggle']) ? sanitize_text_field($_POST['toggle']) : false;
315
- $response = array('Status' => 'fail');
316
- $settings = \wpSPIO()->settings();
317
-
318
- if (! $toggle)
319
- {
320
- $response['Status'] = 'No Toggle';
321
- }
322
-
323
- if ($toggle == 'off')
324
- {
325
- $settings->helpscoutOptin = 0;
326
- $response['Status'] = 'success';
327
- }
328
- elseif($toggle == 'on')
329
- {
330
- $settings->helpscoutOptin = 1;
331
- $response['Status'] = 'success';
332
- }
333
- else
334
- {
335
- $response['Status'] = 'No valid Toggle';
336
- }
337
-
338
- wp_send_json($response);
339
- exit();
340
- }
341
  } // class
45
  'excludePatterns' => array('key' => 'wp-short-pixel-exclude-patterns', 'default' => array(), 'group' => 'options'),
46
  'png2jpg' => array('key' => 'wp-short-pixel-png2jpg', 'default' => 0, 'group' => 'options'),
47
  'excludeSizes' => array('key' => 'wp-short-pixel-excludeSizes', 'default' => array(), 'group' => 'options'),
48
+ 'currentVersion' => array('key' => 'wp-short-pixel-currentVersion', 'default' => null, 'group' => 'options'),
49
 
50
  //CloudFlare
51
  'cloudflareEmail' => array( 'key' => 'wp-short-pixel-cloudflareAPIEmail', 'default' => '', 'group' => 'options'),
225
  }
226
  $trace = debug_backtrace();
227
  trigger_error(
228
+ 'Undefined property via __get(): ' . esc_html($name) .
229
+ ' in ' . esc_html($trace[0]['file']) .
230
+ ' on line ' . esc_html($trace[0]['line']),
231
  E_USER_NOTICE);
232
  return null;
233
  }
309
  }
310
  }
311
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
312
  } // class
readme.txt CHANGED
@@ -4,7 +4,7 @@ Tags: convert webp, optimize images, image optimization, resize, compressor, ima
4
  Requires at least: 4.8.0
5
  Tested up to: 6.0
6
  Requires PHP: 5.6
7
- Stable tag: 5.0.4
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -309,6 +309,26 @@ Add HTTP basic authentication credentials by defining these constants in wp-conf
309
 
310
  == Changelog ==
311
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
312
  = 5.0.4 =
313
  Release date June 22nd, 2022
314
  * Fix: some notifications could not be dismissed because of a jQuery error, kudos to @KZeni for the fix;
4
  Requires at least: 4.8.0
5
  Tested up to: 6.0
6
  Requires PHP: 5.6
7
+ Stable tag: 5.0.5
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
309
 
310
  == Changelog ==
311
 
312
+ = 5.0.5 =
313
+ Release date July 7th, 2022
314
+ * Fix: in some cases the legacy optimization data was not migrated properly, resulting in backup-related errors;
315
+ * Fix: added the possibility to redo the migration of the optimization data when the backups exist;
316
+ * Fix: significantly reduced the number of queries when WP Offload Media is in use, as this was causing slowness in some cases;
317
+ * Fix: the automatic processing now works correctly when using the block editor as well as on other pages where it was broken;
318
+ * Fix: the unlisted thumbnails were not processed correctly and showed up as not optimized;
319
+ * Fix: the integration with the Photo Engine and WP/LR Sync plugins works properly again;
320
+ * Fix: the filter in the Media Library was making the image name go away;
321
+ * Fix: changing the API Key now resets correctly the credits information;
322
+ * Fix: removed a persistent notification about a potential insufficient quota;
323
+ * Fix: the "Optimize now" button works correctly in Custom Media;
324
+ * Fix: the "Extend quota" button works correctly in the Media Library;
325
+ * Fix: other folders from the `wp-content/uplods` folder can now be added as Custom Media folders;
326
+ * Fix: the size exclusions were not working as expected for thumbnails;
327
+ * Fix: updated various pieces of code in accordance with the WordPress Coding Standards;
328
+ * Tweak: the wait time between checking if there is anything to optimize has been lowered;
329
+ * Tweak: added a `clear` function for WP-CLI, to clear the existing queue(s);
330
+ * Language: 3 new string added, 0 updated, 0 fuzzed, and 7 obsoleted.
331
+
332
  = 5.0.4 =
333
  Release date June 22nd, 2022
334
  * Fix: some notifications could not be dismissed because of a jQuery error, kudos to @KZeni for the fix;
res/js/picturefill.min.js DELETED
@@ -1,5 +0,0 @@
1
- /*! picturefill - v3.0.2 - 2016-02-12
2
- * https://scottjehl.github.io/picturefill/
3
- * Copyright (c) 2016 https://github.com/scottjehl/picturefill/blob/master/Authors.txt; Licensed MIT
4
- */
5
- !function(a){var b=navigator.userAgent;a.HTMLPictureElement&&/ecko/.test(b)&&b.match(/rv\:(\d+)/)&&RegExp.$1<45&&addEventListener("resize",function(){var b,c=document.createElement("source"),d=function(a){var b,d,e=a.parentNode;"PICTURE"===e.nodeName.toUpperCase()?(b=c.cloneNode(),e.insertBefore(b,e.firstElementChild),setTimeout(function(){e.removeChild(b)})):(!a._pfLastSize||a.offsetWidth>a._pfLastSize)&&(a._pfLastSize=a.offsetWidth,d=a.sizes,a.sizes+=",100vw",setTimeout(function(){a.sizes=d}))},e=function(){var a,b=document.querySelectorAll("picture > img, img[srcset][sizes]");for(a=0;a<b.length;a++)d(b[a])},f=function(){clearTimeout(b),b=setTimeout(e,99)},g=a.matchMedia&&matchMedia("(orientation: landscape)"),h=function(){f(),g&&g.addListener&&g.addListener(f)};return c.srcset="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",/^[c|i]|d$/.test(document.readyState||"")?h():document.addEventListener("DOMContentLoaded",h),f}())}(window),function(a,b,c){"use strict";function d(a){return" "===a||" "===a||"\n"===a||"\f"===a||"\r"===a}function e(b,c){var d=new a.Image;return d.onerror=function(){A[b]=!1,ba()},d.onload=function(){A[b]=1===d.width,ba()},d.src=c,"pending"}function f(){M=!1,P=a.devicePixelRatio,N={},O={},s.DPR=P||1,Q.width=Math.max(a.innerWidth||0,z.clientWidth),Q.height=Math.max(a.innerHeight||0,z.clientHeight),Q.vw=Q.width/100,Q.vh=Q.height/100,r=[Q.height,Q.width,P].join("-"),Q.em=s.getEmValue(),Q.rem=Q.em}function g(a,b,c,d){var e,f,g,h;return"saveData"===B.algorithm?a>2.7?h=c+1:(f=b-c,e=Math.pow(a-.6,1.5),g=f*e,d&&(g+=.1*e),h=a+g):h=c>1?Math.sqrt(a*b):a,h>c}function h(a){var b,c=s.getSet(a),d=!1;"pending"!==c&&(d=r,c&&(b=s.setRes(c),s.applySetCandidate(b,a))),a[s.ns].evaled=d}function i(a,b){return a.res-b.res}function j(a,b,c){var d;return!c&&b&&(c=a[s.ns].sets,c=c&&c[c.length-1]),d=k(b,c),d&&(b=s.makeUrl(b),a[s.ns].curSrc=b,a[s.ns].curCan=d,d.res||aa(d,d.set.sizes)),d}function k(a,b){var c,d,e;if(a&&b)for(e=s.parseSet(b),a=s.makeUrl(a),c=0;c<e.length;c++)if(a===s.makeUrl(e[c].url)){d=e[c];break}return d}function l(a,b){var c,d,e,f,g=a.getElementsByTagName("source");for(c=0,d=g.length;d>c;c++)e=g[c],e[s.ns]=!0,f=e.getAttribute("srcset"),f&&b.push({srcset:f,media:e.getAttribute("media"),type:e.getAttribute("type"),sizes:e.getAttribute("sizes")})}function m(a,b){function c(b){var c,d=b.exec(a.substring(m));return d?(c=d[0],m+=c.length,c):void 0}function e(){var a,c,d,e,f,i,j,k,l,m=!1,o={};for(e=0;e<h.length;e++)f=h[e],i=f[f.length-1],j=f.substring(0,f.length-1),k=parseInt(j,10),l=parseFloat(j),X.test(j)&&"w"===i?((a||c)&&(m=!0),0===k?m=!0:a=k):Y.test(j)&&"x"===i?((a||c||d)&&(m=!0),0>l?m=!0:c=l):X.test(j)&&"h"===i?((d||c)&&(m=!0),0===k?m=!0:d=k):m=!0;m||(o.url=g,a&&(o.w=a),c&&(o.d=c),d&&(o.h=d),d||c||a||(o.d=1),1===o.d&&(b.has1x=!0),o.set=b,n.push(o))}function f(){for(c(T),i="",j="in descriptor";;){if(k=a.charAt(m),"in descriptor"===j)if(d(k))i&&(h.push(i),i="",j="after descriptor");else{if(","===k)return m+=1,i&&h.push(i),void e();if("("===k)i+=k,j="in parens";else{if(""===k)return i&&h.push(i),void e();i+=k}}else if("in parens"===j)if(")"===k)i+=k,j="in descriptor";else{if(""===k)return h.push(i),void e();i+=k}else if("after descriptor"===j)if(d(k));else{if(""===k)return void e();j="in descriptor",m-=1}m+=1}}for(var g,h,i,j,k,l=a.length,m=0,n=[];;){if(c(U),m>=l)return n;g=c(V),h=[],","===g.slice(-1)?(g=g.replace(W,""),e()):f()}}function n(a){function b(a){function b(){f&&(g.push(f),f="")}function c(){g[0]&&(h.push(g),g=[])}for(var e,f="",g=[],h=[],i=0,j=0,k=!1;;){if(e=a.charAt(j),""===e)return b(),c(),h;if(k){if("*"===e&&"/"===a[j+1]){k=!1,j+=2,b();continue}j+=1}else{if(d(e)){if(a.charAt(j-1)&&d(a.charAt(j-1))||!f){j+=1;continue}if(0===i){b(),j+=1;continue}e=" "}else if("("===e)i+=1;else if(")"===e)i-=1;else{if(","===e){b(),c(),j+=1;continue}if("/"===e&&"*"===a.charAt(j+1)){k=!0,j+=2;continue}}f+=e,j+=1}}}function c(a){return k.test(a)&&parseFloat(a)>=0?!0:l.test(a)?!0:"0"===a||"-0"===a||"+0"===a?!0:!1}var e,f,g,h,i,j,k=/^(?:[+-]?[0-9]+|[0-9]*\.[0-9]+)(?:[eE][+-]?[0-9]+)?(?:ch|cm|em|ex|in|mm|pc|pt|px|rem|vh|vmin|vmax|vw)$/i,l=/^calc\((?:[0-9a-z \.\+\-\*\/\(\)]+)\)$/i;for(f=b(a),g=f.length,e=0;g>e;e++)if(h=f[e],i=h[h.length-1],c(i)){if(j=i,h.pop(),0===h.length)return j;if(h=h.join(" "),s.matchesMedia(h))return j}return"100vw"}b.createElement("picture");var o,p,q,r,s={},t=!1,u=function(){},v=b.createElement("img"),w=v.getAttribute,x=v.setAttribute,y=v.removeAttribute,z=b.documentElement,A={},B={algorithm:""},C="data-pfsrc",D=C+"set",E=navigator.userAgent,F=/rident/.test(E)||/ecko/.test(E)&&E.match(/rv\:(\d+)/)&&RegExp.$1>35,G="currentSrc",H=/\s+\+?\d+(e\d+)?w/,I=/(\([^)]+\))?\s*(.+)/,J=a.picturefillCFG,K="position:absolute;left:0;visibility:hidden;display:block;padding:0;border:none;font-size:1em;width:1em;overflow:hidden;clip:rect(0px, 0px, 0px, 0px)",L="font-size:100%!important;",M=!0,N={},O={},P=a.devicePixelRatio,Q={px:1,"in":96},R=b.createElement("a"),S=!1,T=/^[ \t\n\r\u000c]+/,U=/^[, \t\n\r\u000c]+/,V=/^[^ \t\n\r\u000c]+/,W=/[,]+$/,X=/^\d+$/,Y=/^-?(?:[0-9]+|[0-9]*\.[0-9]+)(?:[eE][+-]?[0-9]+)?$/,Z=function(a,b,c,d){a.addEventListener?a.addEventListener(b,c,d||!1):a.attachEvent&&a.attachEvent("on"+b,c)},$=function(a){var b={};return function(c){return c in b||(b[c]=a(c)),b[c]}},_=function(){var a=/^([\d\.]+)(em|vw|px)$/,b=function(){for(var a=arguments,b=0,c=a[0];++b in a;)c=c.replace(a[b],a[++b]);return c},c=$(function(a){return"return "+b((a||"").toLowerCase(),/\band\b/g,"&&",/,/g,"||",/min-([a-z-\s]+):/g,"e.$1>=",/max-([a-z-\s]+):/g,"e.$1<=",/calc([^)]+)/g,"($1)",/(\d+[\.]*[\d]*)([a-z]+)/g,"($1 * e.$2)",/^(?!(e.[a-z]|[0-9\.&=|><\+\-\*\(\)\/])).*/gi,"")+";"});return function(b,d){var e;if(!(b in N))if(N[b]=!1,d&&(e=b.match(a)))N[b]=e[1]*Q[e[2]];else try{N[b]=new Function("e",c(b))(Q)}catch(f){}return N[b]}}(),aa=function(a,b){return a.w?(a.cWidth=s.calcListLength(b||"100vw"),a.res=a.w/a.cWidth):a.res=a.d,a},ba=function(a){if(t){var c,d,e,f=a||{};if(f.elements&&1===f.elements.nodeType&&("IMG"===f.elements.nodeName.toUpperCase()?f.elements=[f.elements]:(f.context=f.elements,f.elements=null)),c=f.elements||s.qsa(f.context||b,f.reevaluate||f.reselect?s.sel:s.selShort),e=c.length){for(s.setupRun(f),S=!0,d=0;e>d;d++)s.fillImg(c[d],f);s.teardownRun(f)}}};o=a.console&&console.warn?function(a){console.warn(a)}:u,G in v||(G="src"),A["image/jpeg"]=!0,A["image/gif"]=!0,A["image/png"]=!0,A["image/svg+xml"]=b.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Image","1.1"),s.ns=("pf"+(new Date).getTime()).substr(0,9),s.supSrcset="srcset"in v,s.supSizes="sizes"in v,s.supPicture=!!a.HTMLPictureElement,s.supSrcset&&s.supPicture&&!s.supSizes&&!function(a){v.srcset="data:,a",a.src="data:,a",s.supSrcset=v.complete===a.complete,s.supPicture=s.supSrcset&&s.supPicture}(b.createElement("img")),s.supSrcset&&!s.supSizes?!function(){var a="data:image/gif;base64,R0lGODlhAgABAPAAAP///wAAACH5BAAAAAAALAAAAAACAAEAAAICBAoAOw==",c="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",d=b.createElement("img"),e=function(){var a=d.width;2===a&&(s.supSizes=!0),q=s.supSrcset&&!s.supSizes,t=!0,setTimeout(ba)};d.onload=e,d.onerror=e,d.setAttribute("sizes","9px"),d.srcset=c+" 1w,"+a+" 9w",d.src=c}():t=!0,s.selShort="picture>img,img[srcset]",s.sel=s.selShort,s.cfg=B,s.DPR=P||1,s.u=Q,s.types=A,s.setSize=u,s.makeUrl=$(function(a){return R.href=a,R.href}),s.qsa=function(a,b){return"querySelector"in a?a.querySelectorAll(b):[]},s.matchesMedia=function(){return a.matchMedia&&(matchMedia("(min-width: 0.1em)")||{}).matches?s.matchesMedia=function(a){return!a||matchMedia(a).matches}:s.matchesMedia=s.mMQ,s.matchesMedia.apply(this,arguments)},s.mMQ=function(a){return a?_(a):!0},s.calcLength=function(a){var b=_(a,!0)||!1;return 0>b&&(b=!1),b},s.supportsType=function(a){return a?A[a]:!0},s.parseSize=$(function(a){var b=(a||"").match(I);return{media:b&&b[1],length:b&&b[2]}}),s.parseSet=function(a){return a.cands||(a.cands=m(a.srcset,a)),a.cands},s.getEmValue=function(){var a;if(!p&&(a=b.body)){var c=b.createElement("div"),d=z.style.cssText,e=a.style.cssText;c.style.cssText=K,z.style.cssText=L,a.style.cssText=L,a.appendChild(c),p=c.offsetWidth,a.removeChild(c),p=parseFloat(p,10),z.style.cssText=d,a.style.cssText=e}return p||16},s.calcListLength=function(a){if(!(a in O)||B.uT){var b=s.calcLength(n(a));O[a]=b?b:Q.width}return O[a]},s.setRes=function(a){var b;if(a){b=s.parseSet(a);for(var c=0,d=b.length;d>c;c++)aa(b[c],a.sizes)}return b},s.setRes.res=aa,s.applySetCandidate=function(a,b){if(a.length){var c,d,e,f,h,k,l,m,n,o=b[s.ns],p=s.DPR;if(k=o.curSrc||b[G],l=o.curCan||j(b,k,a[0].set),l&&l.set===a[0].set&&(n=F&&!b.complete&&l.res-.1>p,n||(l.cached=!0,l.res>=p&&(h=l))),!h)for(a.sort(i),f=a.length,h=a[f-1],d=0;f>d;d++)if(c=a[d],c.res>=p){e=d-1,h=a[e]&&(n||k!==s.makeUrl(c.url))&&g(a[e].res,c.res,p,a[e].cached)?a[e]:c;break}h&&(m=s.makeUrl(h.url),o.curSrc=m,o.curCan=h,m!==k&&s.setSrc(b,h),s.setSize(b))}},s.setSrc=function(a,b){var c;a.src=b.url,"image/svg+xml"===b.set.type&&(c=a.style.width,a.style.width=a.offsetWidth+1+"px",a.offsetWidth+1&&(a.style.width=c))},s.getSet=function(a){var b,c,d,e=!1,f=a[s.ns].sets;for(b=0;b<f.length&&!e;b++)if(c=f[b],c.srcset&&s.matchesMedia(c.media)&&(d=s.supportsType(c.type))){"pending"===d&&(c=d),e=c;break}return e},s.parseSets=function(a,b,d){var e,f,g,h,i=b&&"PICTURE"===b.nodeName.toUpperCase(),j=a[s.ns];(j.src===c||d.src)&&(j.src=w.call(a,"src"),j.src?x.call(a,C,j.src):y.call(a,C)),(j.srcset===c||d.srcset||!s.supSrcset||a.srcset)&&(e=w.call(a,"srcset"),j.srcset=e,h=!0),j.sets=[],i&&(j.pic=!0,l(b,j.sets)),j.srcset?(f={srcset:j.srcset,sizes:w.call(a,"sizes")},j.sets.push(f),g=(q||j.src)&&H.test(j.srcset||""),g||!j.src||k(j.src,f)||f.has1x||(f.srcset+=", "+j.src,f.cands.push({url:j.src,d:1,set:f}))):j.src&&j.sets.push({srcset:j.src,sizes:null}),j.curCan=null,j.curSrc=c,j.supported=!(i||f&&!s.supSrcset||g&&!s.supSizes),h&&s.supSrcset&&!j.supported&&(e?(x.call(a,D,e),a.srcset=""):y.call(a,D)),j.supported&&!j.srcset&&(!j.src&&a.src||a.src!==s.makeUrl(j.src))&&(null===j.src?a.removeAttribute("src"):a.src=j.src),j.parsed=!0},s.fillImg=function(a,b){var c,d=b.reselect||b.reevaluate;a[s.ns]||(a[s.ns]={}),c=a[s.ns],(d||c.evaled!==r)&&((!c.parsed||b.reevaluate)&&s.parseSets(a,a.parentNode,b),c.supported?c.evaled=r:h(a))},s.setupRun=function(){(!S||M||P!==a.devicePixelRatio)&&f()},s.supPicture?(ba=u,s.fillImg=u):!function(){var c,d=a.attachEvent?/d$|^c/:/d$|^c|^i/,e=function(){var a=b.readyState||"";f=setTimeout(e,"loading"===a?200:999),b.body&&(s.fillImgs(),c=c||d.test(a),c&&clearTimeout(f))},f=setTimeout(e,b.body?9:99),g=function(a,b){var c,d,e=function(){var f=new Date-d;b>f?c=setTimeout(e,b-f):(c=null,a())};return function(){d=new Date,c||(c=setTimeout(e,b))}},h=z.clientHeight,i=function(){M=Math.max(a.innerWidth||0,z.clientWidth)!==Q.width||z.clientHeight!==h,h=z.clientHeight,M&&s.fillImgs()};Z(a,"resize",g(i,99)),Z(b,"readystatechange",e)}(),s.picturefill=ba,s.fillImgs=ba,s.teardownRun=u,ba._=s,a.picturefillCFG={pf:s,push:function(a){var b=a.shift();"function"==typeof s[b]?s[b].apply(s,a):(B[b]=a[0],S&&s.fillImgs({reselect:!0}))}};for(;J&&J.length;)a.picturefillCFG.push(J.shift());a.picturefill=ba,"object"==typeof module&&"object"==typeof module.exports?module.exports=ba:"function"==typeof define&&define.amd&&define("picturefill",function(){return ba}),s.supPicture||(A["image/webp"]=e("image/webp","data:image/webp;base64,UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAABBxAR/Q9ERP8DAABWUDggGAAAADABAJ0BKgEAAQADADQlpAADcAD++/1QAA=="))}(window,document);
 
 
 
 
 
res/js/screens/screen-bulk.js CHANGED
@@ -291,9 +291,10 @@ console.log("Screen Init Done", initMedia, initCustom);
291
  if (qStatus == 'PREPARING_DONE' || qStatus == 'PREPARING_RECOUNT')
292
  {
293
  console.log('Queue status: preparing done');
294
- this.UpdatePanelStatus('loaded', 'selection');
295
  this.SwitchPanel('summary');
296
- this.processor.SetInterval(-1); // back to default.
 
297
 
298
  }
299
  if (qStatus == 'QUEUE_EMPTY')
@@ -938,9 +939,6 @@ console.log("Screen Init Done", initMedia, initCustom);
938
  }
939
  var data = {screen_action: 'startRestoreAll', callback: 'shortpixel.startRestoreAll', queues: queues}; //
940
 
941
- this.SwitchPanel('selection');
942
- this.UpdatePanelStatus('loading', 'selection');
943
-
944
  // Prepare should happen after selecting what the optimize.
945
  window.addEventListener('shortpixel.startRestoreAll', this.PrepareBulk.bind(this), {'once': true} );
946
  window.addEventListener('shortpixel.bulk.onSwitchPanel', this.StartBulk.bind(this), {'once': true});
@@ -949,11 +947,9 @@ console.log("Screen Init Done", initMedia, initCustom);
949
 
950
  this.BulkMigrateAll = function (event)
951
  {
952
- console.log('Start Migrate All');
953
  var data = {screen_action: 'startMigrateAll', callback: 'shortpixel.startMigrateAll'}; //
954
 
955
  this.UpdatePanelStatus('loading', 'selection');
956
-
957
  this.SwitchPanel('selection');
958
 
959
  //this.SwitchPanel('process');
@@ -965,7 +961,7 @@ console.log("Screen Init Done", initMedia, initCustom);
965
  }
966
  this.BulkRemoveLegacy = function (event)
967
  {
968
- console.log('Start Remove Legacy');
969
  var data = {screen_action: 'startRemoveLegacy', callback: 'shortpixel.startRemoveLegacy'}; //
970
 
971
  this.SwitchPanel('selection');
@@ -977,6 +973,15 @@ console.log("Screen Init Done", initMedia, initCustom);
977
  window.addEventListener('shortpixel.bulk.onSwitchPanel', this.StartBulk.bind(this), {'once': true});
978
  this.processor.AjaxRequest(data);
979
  }
 
 
 
 
 
 
 
 
 
980
 
981
 
982
  // Opening of Log files on the dashboard
291
  if (qStatus == 'PREPARING_DONE' || qStatus == 'PREPARING_RECOUNT')
292
  {
293
  console.log('Queue status: preparing done');
294
+
295
  this.SwitchPanel('summary');
296
+ this.UpdatePanelStatus('loaded', 'selection');
297
+ this.processor.SetInterval(-1); // back to default.
298
 
299
  }
300
  if (qStatus == 'QUEUE_EMPTY')
939
  }
940
  var data = {screen_action: 'startRestoreAll', callback: 'shortpixel.startRestoreAll', queues: queues}; //
941
 
 
 
 
942
  // Prepare should happen after selecting what the optimize.
943
  window.addEventListener('shortpixel.startRestoreAll', this.PrepareBulk.bind(this), {'once': true} );
944
  window.addEventListener('shortpixel.bulk.onSwitchPanel', this.StartBulk.bind(this), {'once': true});
947
 
948
  this.BulkMigrateAll = function (event)
949
  {
 
950
  var data = {screen_action: 'startMigrateAll', callback: 'shortpixel.startMigrateAll'}; //
951
 
952
  this.UpdatePanelStatus('loading', 'selection');
 
953
  this.SwitchPanel('selection');
954
 
955
  //this.SwitchPanel('process');
961
  }
962
  this.BulkRemoveLegacy = function (event)
963
  {
964
+
965
  var data = {screen_action: 'startRemoveLegacy', callback: 'shortpixel.startRemoveLegacy'}; //
966
 
967
  this.SwitchPanel('selection');
973
  window.addEventListener('shortpixel.bulk.onSwitchPanel', this.StartBulk.bind(this), {'once': true});
974
  this.processor.AjaxRequest(data);
975
  }
976
+ this.StartBulkOperation = function (event)
977
+ {
978
+ this.PrepareBulk();
979
+
980
+ this.UpdatePanelStatus('loading', 'selection');
981
+ this.SwitchPanel('selection');
982
+
983
+
984
+ }
985
 
986
 
987
  // Opening of Log files on the dashboard
res/js/screens/screen-media.js CHANGED
@@ -222,7 +222,6 @@ var ShortPixelScreen = function (MainScreen, processor)
222
  data.id = id;
223
  data.type = 'media';
224
  data.screen_action = 'restoreItem';
225
- //data.callback = 'this.loadItemView';
226
  // AjaxRequest should return result, which will go through Handleresponse, then LoadiTemView.
227
  this.processor.AjaxRequest(data);
228
  //var id = data.id;
@@ -241,6 +240,24 @@ var ShortPixelScreen = function (MainScreen, processor)
241
 
242
  this.processor.AjaxRequest(data);
243
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
244
  this.Optimize = function (id)
245
  {
246
 
222
  data.id = id;
223
  data.type = 'media';
224
  data.screen_action = 'restoreItem';
 
225
  // AjaxRequest should return result, which will go through Handleresponse, then LoadiTemView.
226
  this.processor.AjaxRequest(data);
227
  //var id = data.id;
240
 
241
  this.processor.AjaxRequest(data);
242
  }
243
+ this.RedoLegacy = function(id)
244
+ {
245
+ var data = {
246
+ id: id,
247
+ type: 'media',
248
+ screen_action: 'redoLegacy',
249
+ }
250
+ data.callback = 'shortpixel.LoadItemView';
251
+
252
+ window.addEventListener('shortpixel.LoadItemView', function (e) {
253
+ var itemData = { id: e.detail.media.id, type: 'media' };
254
+ this.processor.timesEmpty = 0; // reset the defer on this.
255
+ this.processor.LoadItemView(itemData);
256
+
257
+ }.bind(this), {'once': true} );
258
+
259
+ this.processor.AjaxRequest(data);
260
+ }
261
  this.Optimize = function (id)
262
  {
263
 
res/js/shortpixel-processor.js CHANGED
@@ -21,7 +21,7 @@ window.ShortPixelProcessor =
21
  isActive: false,
22
  defaultInterval: 3000, // @todo customize this from backend var, hook filter. default is onload interval
23
  interval: 3000, // is current interval. When nothing to be done increases
24
- deferInterval: 60000, // how long to wait between interval to check for new items.
25
  screen: null, // UI Object
26
  tooltip: null,
27
  isBulkPage: false,
@@ -205,7 +205,9 @@ window.ShortPixelProcessor =
205
  Process: function()
206
  {
207
  if (this.worker === null)
 
208
  this.LoadWorker(); // JIT worker loading
 
209
 
210
  //this.tooltip.DoingProcess();
211
  this.worker.postMessage({action: 'process', 'nonce' : this.nonce['process']});
@@ -226,7 +228,7 @@ window.ShortPixelProcessor =
226
  //if (this.timesEmpty >= 5) // conflicts with the stop defer.
227
  // this.interval = 2000 + (this.timesEmpty * 1000); // every time it turns up empty, second slower.
228
 
229
- console.log('Processor: Run Process');
230
 
231
  this.timer = window.setTimeout(this.Process.bind(this), this.interval);
232
  },
@@ -298,6 +300,7 @@ window.ShortPixelProcessor =
298
  if (data.status == true && data.response) // data status is from shortpixel worker, not the response object
299
  {
300
  var response = data.response;
 
301
  if ( response.callback)
302
  {
303
  console.log('Running callback : ' + response.callback);
@@ -379,8 +382,11 @@ window.ShortPixelProcessor =
379
  this.Debug(message, 'error');
380
  }
381
 
382
- if (this.workerErrors >= 3)
 
383
  this.StopProcess();
 
 
384
  else
385
  this.StopProcess({ defer: true });
386
 
@@ -474,7 +480,7 @@ window.ShortPixelProcessor =
474
 
475
  if (combinedStatus == 100)
476
  {
477
-
478
  return false; // no status in this request.
479
  }
480
 
21
  isActive: false,
22
  defaultInterval: 3000, // @todo customize this from backend var, hook filter. default is onload interval
23
  interval: 3000, // is current interval. When nothing to be done increases
24
+ deferInterval: 15000, // how long to wait between interval to check for new items.
25
  screen: null, // UI Object
26
  tooltip: null,
27
  isBulkPage: false,
205
  Process: function()
206
  {
207
  if (this.worker === null)
208
+ {
209
  this.LoadWorker(); // JIT worker loading
210
+ }
211
 
212
  //this.tooltip.DoingProcess();
213
  this.worker.postMessage({action: 'process', 'nonce' : this.nonce['process']});
228
  //if (this.timesEmpty >= 5) // conflicts with the stop defer.
229
  // this.interval = 2000 + (this.timesEmpty * 1000); // every time it turns up empty, second slower.
230
 
231
+ console.log('Processor: Run Process in ' + this.interval);
232
 
233
  this.timer = window.setTimeout(this.Process.bind(this), this.interval);
234
  },
300
  if (data.status == true && data.response) // data status is from shortpixel worker, not the response object
301
  {
302
  var response = data.response;
303
+ this.workerErrors = 0;
304
  if ( response.callback)
305
  {
306
  console.log('Running callback : ' + response.callback);
382
  this.Debug(message, 'error');
383
  }
384
 
385
+ if (this.workerErrors >= 5)
386
+ {
387
  this.StopProcess();
388
+ this.ShutDownWorker();
389
+ }
390
  else
391
  this.StopProcess({ defer: true });
392
 
480
 
481
  if (combinedStatus == 100)
482
  {
483
+ this.StopProcess({ defer: true });
484
  return false; // no status in this request.
485
  }
486
 
res/js/shortpixel-worker.js CHANGED
@@ -101,7 +101,7 @@ var SpWorker = {
101
  {
102
  if (this && ! this.stopped)
103
  {
104
- console.error('Worker.js reporting issue');
105
  postMessage({'status' : false, message: response.status + ' ' + response.statusText});
106
  }
107
  }
101
  {
102
  if (this && ! this.stopped)
103
  {
104
+ console.error('Worker.js reporting issue', response);
105
  postMessage({'status' : false, message: response.status + ' ' + response.statusText});
106
  }
107
  }
shortpixel-plugin.php CHANGED
@@ -1,5 +1,6 @@
1
  <?php
2
  namespace ShortPixel;
 
3
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
4
  use ShortPixel\Notices\NoticeController as Notices;
5
  use ShortPixel\Controller\OptimizeController as OptimizeController;
@@ -9,7 +10,7 @@ use ShortPixel\Controller\AdminController as AdminController;
9
  use ShortPixel\Controller\OtherMediaController as OtherMediaController;
10
  use ShortPixel\NextGenController as NextGenController;
11
 
12
- //use ShortPixel\Controller;
13
 
14
  use ShortPixel\Controller\Queue\MediaLibraryQueue as MediaLibraryQueue;
15
  use ShortPixel\Controller\Queue\CustomQueue as CustomQueue;
@@ -17,669 +18,627 @@ use ShortPixel\Controller\Queue\CustomQueue as CustomQueue;
17
  use ShortPixel\Helper\InstallHelper as InstallHelper;
18
 
19
  /** Plugin class
20
- * This class is meant for: WP Hooks, init of runtime and Controller Routing.
21
-
22
- */
23
- class ShortPixelPlugin
24
- {
25
- private static $instance;
26
- protected static $modelsLoaded = array(); // don't require twice, limit amount of require looksups..
27
-
28
- // private $paths = array('class', 'class/controller', 'class/external', 'class/controller/views'); // classes that are autoloaded
29
 
30
- protected $is_noheaders = false;
 
31
 
32
- protected $plugin_path;
33
- protected $plugin_url;
34
 
35
- protected $shortPixel; // shortpixel megaclass
36
- protected $settings; // settings object.
37
 
38
- protected $admin_pages = array(); // admin page hooks.
 
39
 
40
- public function __construct()
41
- {
42
- $this->plugin_path = plugin_dir_path(SHORTPIXEL_PLUGIN_FILE);
43
- $this->plugin_url = plugin_dir_url(SHORTPIXEL_PLUGIN_FILE);
44
 
45
- //$this->initHooks();
46
- add_action('plugins_loaded', array($this, 'lowInit'), 5); // early as possible init.
47
- }
48
 
 
 
 
49
 
50
- /** LowInit after all Plugins are loaded. Core WP function can still be missing. This should mostly add hooks */
51
- public function lowInit()
52
- {
53
- if(isset($_REQUEST['noheader'])) {
54
- $this->is_noheaders = true;
55
- }
56
 
57
- /* Filter to prevent SPIO from starting. This can be used by third-parties to prevent init when needed for a particular situation.
58
- * Hook into plugins_loaded with priority lower than 5 */
59
- $init = apply_filters('shortpixel/plugin/init', true);
60
 
61
- if (! $init)
62
- {
63
- return;
64
- }
 
 
65
 
66
- $front = new Controller\FrontController();
67
- $admin = Controller\AdminController::getInstance();
68
- $adminNotices = Controller\AdminNoticesController::getInstance(); // Hook in the admin notices.
 
69
 
70
- $this->initHooks();
71
- $this->ajaxHooks();
 
72
 
 
 
 
73
 
 
 
74
 
75
  if ( defined( 'WP_CLI' ) && WP_CLI ) {
76
- WPCliController::getInstance();
77
  }
78
 
79
- add_action('admin_init', array($this, 'init'));
80
- }
81
 
82
 
83
- /** Mainline Admin Init. Tasks that can be loaded later should go here */
84
- public function init()
85
- {
86
  // This runs activation thing. Should be -after- init
87
  $this->check_plugin_version();
88
 
89
- $notices = Notices::getInstance(); // This hooks the ajax listener
90
  $quotaController = QuotaController::getInstance();
91
  $quotaController->getQuota();
92
 
 
93
 
94
- }
95
-
96
- /** Function to get plugin settings
97
- *
98
- * @return SettingsModel The settings model object.
99
- */
100
- public function settings()
101
- {
102
- if (is_null($this->settings))
103
- $this->settings = new \WPShortPixelSettings();
104
-
105
- return $this->settings;
106
- }
107
 
108
- /** Function to get all enviromental variables
109
- *
110
- * @return EnvironmentModel
111
- */
112
- public function env()
113
- {
114
- return Model\EnvironmentModel::getInstance();
115
- }
116
 
117
- public function fileSystem()
118
- {
119
- return new Controller\FileSystemController();
120
- }
 
 
 
121
 
122
- /** Create instance. This should not be needed to call anywhere else than main plugin file
123
- * This should not be called *after* plugins_loaded action
124
- **/
125
- public static function getInstance()
126
- {
127
- if (is_null(self::$instance))
128
- {
129
- self::$instance = new ShortPixelPlugin();
130
- }
131
- return self::$instance;
132
 
133
- }
 
 
 
 
 
 
 
134
 
 
135
 
136
- /** Hooks for all WordPress related hooks
137
- * For now hooks in the lowInit, asap.
138
- */
139
- public function initHooks()
140
- {
141
- add_action('admin_menu', array($this,'admin_pages'));
142
- add_action('admin_enqueue_scripts', array($this, 'admin_scripts')); // admin scripts
143
- add_action('admin_enqueue_scripts', array($this, 'admin_styles')); // admin styles
144
- add_action('admin_enqueue_scripts', array($this, 'load_admin_scripts'), 90); // loader via route.
145
- // defer notices a little to allow other hooks ( notable adminnotices )
146
 
 
 
 
 
 
 
 
 
 
 
147
 
148
- $optimizeController = new OptimizeController();
149
- add_action( 'shortpixel-thumbnails-regenerated', array( $optimizeController, 'thumbnailsChangedHook' ), 10, 4);
150
 
151
- // Media Library
152
- add_action('load-upload.php', array($this, 'route'));
153
 
154
- add_action( 'load-post.php', array( $this, 'route') );
155
 
156
- $admin = AdminController::getInstance();
157
 
158
- // Handle for EMR
159
- add_action('wp_handle_replace', array($admin,'handleReplaceHook'));
160
 
161
  // Action / hook for who wants to use CRON. Please refer to manual / support to prevent loss of credits.
162
- add_action('shortpixel/hook/processqueue', array($admin, 'processQueueHook'));
163
 
164
-
165
- if ($this->env()->is_autoprocess)
166
- {
167
- // compat filter to shortcircuit this in cases. (see external - visualcomposer)
168
- if (apply_filters('shortpixel/init/automedialibrary', true))
169
- {
170
- if($this->settings()->png2jpg) {
171
 
172
  /*
173
  This processing off because it doesn't make sense to already start this before optimizing, which will happen via queue.
174
- add_action( 'add_attachment', array($admin,'handlePng2JpgHook'));
175
- add_action( 'wp_handle_upload', array($admin,'handlePng2JpgHook'));
176
 
177
- // @integration MediaPress
178
- add_action( 'mpp_handle_upload', array($admin,'handlePng2JpgHook'));
179
  */
180
- }
181
-
182
- add_action( 'shortpixel-thumbnails-before-regenerate', array( $admin, 'preventImageHook' ), 10, 1);
183
-
184
- add_action("enable-media-replace-upload-done", array($admin, 'handleReplaceEnqueue'), 10,3);
185
 
186
- add_filter( 'wp_generate_attachment_metadata', array($admin,'handleImageUploadHook'), 10, 2 );
187
- // @integration MediaPress
188
- add_filter( 'mpp_generate_metadata', array($admin,'handleImageUploadHook'), 10, 2 );
189
- }
190
- }
191
 
 
192
 
193
- load_plugin_textdomain('shortpixel-image-optimiser', false, plugin_basename(dirname( SHORTPIXEL_PLUGIN_FILE )).'/lang');
194
-
195
- $isAdminUser = current_user_can( 'manage_options' ); // @todo This should be in env
 
 
196
 
197
- $this->env()->setDefaultViewModeList();//set default mode as list. only @ first run
198
 
199
- add_filter( 'plugin_action_links_' . plugin_basename(SHORTPIXEL_PLUGIN_FILE), array($admin, 'generatePluginLinks'));//for plugin settings page
200
 
201
- //for cleaning up the WebP images when an attachment is deleted
202
- add_action( 'delete_attachment', array( $admin, 'onDeleteAttachment') );
203
- add_action('mime_types', array($admin, 'addMimes'));
204
 
205
- // integration with WP/LR Sync plugin
206
- add_action( 'wplr_update_media', array( AjaxController::getInstance() , 'onWpLrUpdateMedia' ), 10, 2);
207
 
208
- add_action( 'admin_bar_menu', array( $admin, 'toolbar_shortpixel_processing'), 999 );
 
 
209
 
 
 
210
 
211
- if($isAdminUser) {
212
- //toolbar notifications
213
- // add_action( 'wp_head', array( $this, 'headCSS')); // for the front-end
214
 
215
- //deactivate conflicting plugins if found
216
- add_action( 'admin_post_shortpixel_deactivate_conflict_plugin', array('\ShortPixel\Helper\InstallHelper', 'deactivateConflictingPlugin'));
 
217
 
218
- //only if the key is not yet valid or the user hasn't bought any credits.
219
- // @todo This should not be done here.
220
- $settings = $this->settings();
221
- $stats = $settings->currentStats;
222
- $totalCredits = isset($stats["APICallsQuotaNumeric"]) ? $stats['APICallsQuotaNumeric'] + $stats['APICallsQuotaOneTimeNumeric'] : 0;
223
- if(true || !$settings->verifiedKey || $totalCredits < 4000) {
224
- require_once ('class/view/shortpixel-feedback.php');
225
- new ShortPixelFeedback( SHORTPIXEL_PLUGIN_FILE, 'shortpixel-image-optimiser');
226
- }
227
- }
228
 
 
 
 
 
 
 
 
 
 
 
229
 
230
- }
231
 
232
- protected function ajaxHooks()
233
- {
234
 
235
- // Ajax hooks. Should always be prepended with ajax_ and *must* check on nonce in function
236
- add_action( 'wp_ajax_shortpixel_image_processing', array(AjaxController::getInstance(), 'ajax_processQueue') );
237
 
238
- // Custom Media
239
- add_action('wp_ajax_shortpixel_browse_content', array(OtherMediaController::getInstance(), 'ajaxBrowseContent'));
240
- add_action('wp_ajax_shortpixel_get_backup_size', array(AjaxController::getInstance(), 'ajax_getBackupFolderSize'));
241
 
242
- add_action('wp_ajax_shortpixel_propose_upgrade', array(AjaxController::getInstance(), 'ajax_proposeQuotaUpgrade'));
243
- add_action('wp_ajax_shortpixel_check_quota', array(AjaxController::getInstance(), 'ajax_checkquota'));
244
 
245
- // @todo should probably go through ajaxrequest.
246
- add_action( 'wp_ajax_shortpixel_get_comparer_data', array(AjaxController::getInstance(), 'ajax_getComparerData'));
247
 
248
- add_action( 'wp_ajax_shortpixel_ajaxRequest', array(AjaxController::getInstance(), 'ajaxRequest'));
249
 
250
  // Used by processor
251
- add_action( 'wp_ajax_shortpixel_get_item_view', array(AjaxController::getInstance(), 'ajax_getItemView'));
252
-
253
- }
254
 
255
- /** Hook in our admin pages */
256
- public function admin_pages()
257
- {
258
- $admin_pages = array();
259
- // settings page
260
- $admin_pages[] = add_options_page( __('ShortPixel Settings','shortpixel-image-optimiser'), 'ShortPixel', 'manage_options', 'wp-shortpixel-settings', array($this, 'route'));
261
 
262
- $otherMediaController = OtherMediaController::getInstance();
263
- if ($otherMediaController->hasCustomImages())
264
- {
265
- /*translators: title and menu name for the Other media page*/
266
- $admin_pages[] = add_media_page( __('Custom Media Optimized by ShortPixel','shortpixel-image-optimiser'), __('Custom Media','shortpixel-image-optimiser'), 'edit_others_posts', 'wp-short-pixel-custom', array( $this, 'route' ) );
267
- }
268
- /*translators: title and menu name for the Bulk Processing page*/
269
- $admin_pages[] = add_media_page( __('ShortPixel Bulk Process','shortpixel-image-optimiser'), __('Bulk ShortPixel','shortpixel-image-optimiser'), 'edit_others_posts', 'wp-short-pixel-bulk', array( $this, 'route' ) );
270
 
271
- $this->admin_pages = $admin_pages;
272
- }
 
 
 
 
 
273
 
 
 
274
 
275
- /** All scripts should be registed, not enqueued here (unless global wp-admin is needed )
276
- *
277
- * Not all those registered must be enqueued however.
278
- */
279
- public function admin_scripts($hook_suffix)
280
- {
281
 
282
- $settings = \wpSPIO()->settings();
283
- $ajaxController = AjaxController::getInstance();
 
 
 
284
 
285
- $secretKey = $ajaxController->getProcessorKey();
 
286
 
287
- $keyControl = \ShortPixel\Controller\ApiKeyController::getInstance();
288
- $apikey = $keyControl->getKeyForDisplay();
289
 
290
- $is_bulk_page = \wpSPIO()->env()->is_bulk_page;
 
291
 
292
- $optimizeController = new OptimizeController();
293
- $optimizeController->setBulk($is_bulk_page);
294
 
295
- $quotaController = QuotaController::getInstance();
 
296
 
 
297
 
298
- // FileTree in Settings
299
- wp_register_script('sp-file-tree', plugins_url('/res/js/sp-file-tree.min.js',SHORTPIXEL_PLUGIN_FILE), array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true );
300
 
301
- wp_register_script('jquery.knob.min.js', plugins_url('/res/js/jquery.knob.min.js',SHORTPIXEL_PLUGIN_FILE), array(),SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true );
302
 
303
- wp_register_script('jquery.tooltip.min.js', plugins_url('/res/js/jquery.tooltip.min.js',SHORTPIXEL_PLUGIN_FILE), array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true );
304
 
305
- wp_register_script('shortpixel-debug', plugins_url('/res/js/debug.js',SHORTPIXEL_PLUGIN_FILE), array('jquery', 'jquery-ui-draggable'), SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true);
306
 
307
- wp_register_script ('shortpixel-tooltip', plugins_url('/res/js/shortpixel-tooltip.js',SHORTPIXEL_PLUGIN_FILE), array('jquery' ), SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true);
308
- wp_register_script('shortpixel-settings', plugins_url('res/js/shortpixel-settings.js', SHORTPIXEL_PLUGIN_FILE), array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true);
309
 
310
- wp_register_script('shortpixel-processor', plugins_url('/res/js/shortpixel-processor.js',SHORTPIXEL_PLUGIN_FILE), array('jquery', 'shortpixel-tooltip' ), SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true);
311
 
312
  // How often JS processor asks for next tick on server. Low for fastestness and high loads, high number for surviving servers.
313
- $interval = apply_filters('shortpixel/processor/interval', 3000);
314
 
315
  // If the queue is empty how often to check if something new appeared from somewhere. Excluding the manual items added by current processor user.
316
- $deferInterval = apply_filters('shortpixel/process/deferInterval', 60000);
317
 
318
- wp_localize_script('shortpixel-processor', 'ShortPixelProcessorData', array(
319
- 'bulkSecret' => $secretKey,
320
- 'isBulkPage' => (bool) $is_bulk_page,
321
- 'screenURL' => false,
322
- 'workerURL' => $this->plugin_url('res/js/shortpixel-worker.js'),
323
- 'nonce_process' => wp_create_nonce('processing'),
324
- 'nonce_exit' => wp_create_nonce('exit_process'),
325
- 'nonce_itemview' => wp_create_nonce('item_view'),
326
- 'nonce_ajaxrequest' => wp_create_nonce('ajax_request'),
327
- 'startData' => (\wpSPIO()->env()->is_screen_to_use) ? $optimizeController->getStartupData() : false,
328
- 'interval' => $interval,
329
- 'deferInterval' => $deferInterval,
 
 
 
330
 
331
- ));
 
332
 
333
- /*** SCREENS **/
334
- wp_register_script ('shortpixel-screen-media', plugins_url('/res/js/screens/screen-media.js',SHORTPIXEL_PLUGIN_FILE), array('jquery', 'shortpixel-processor' ), SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true);
335
 
336
- wp_register_script ('shortpixel-screen-custom', plugins_url('/res/js/screens/screen-custom.js',SHORTPIXEL_PLUGIN_FILE), array('jquery', 'shortpixel-processor' ), SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true);
337
 
338
- wp_register_script ('shortpixel-screen-nolist', plugins_url('/res/js/screens/screen-nolist.js',SHORTPIXEL_PLUGIN_FILE), array('jquery', 'shortpixel-processor' ), SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true);
339
 
340
- wp_register_script ('shortpixel-screen-bulk', plugins_url('/res/js/screens/screen-bulk.js',SHORTPIXEL_PLUGIN_FILE), array('jquery', 'shortpixel-processor' ), SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true);
341
 
342
- $panel = isset($_GET['panel']) ? sanitize_text_field($_GET['panel']) : false;
 
343
 
344
  $bulkLocalize = array(
345
- 'endBulk' => __('This will stop the bulk processing and take you back to the start. Are you sure you want to do this?', 'shortpixel-image-optimiser'),
346
- 'reloadURL' => admin_url('upload.php?page=wp-short-pixel-bulk'),
347
- );
348
- if ($panel)
349
  $bulkLocalize['panel'] = $panel;
 
350
 
351
- // screen translations. Can all be loaded on the same var, since only one screen can be active.
352
- wp_localize_script('shortpixel-screen-bulk', 'shortPixelScreen', $bulkLocalize );
353
-
354
- wp_register_script('shortpixel', plugins_url('/res/js/shortpixel.js',SHORTPIXEL_PLUGIN_FILE), array('jquery', 'jquery.knob.min.js'), SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true);
355
-
356
-
357
- // Using an Array within another Array to protect the primitive values from being cast to strings
358
- $ShortPixelConstants = array(array(
359
- 'WP_PLUGIN_URL'=>plugins_url( '', SHORTPIXEL_PLUGIN_FILE ),
360
- 'WP_ADMIN_URL'=>admin_url(),
361
- 'API_IS_ACTIVE' => $keyControl->keyIsVerified(),
362
- 'FRONT_BOOTSTRAP'=> $settings->frontBootstrap && (!isset($settings->lastBackAction) || (time() - $settings->lastBackAction > 600)) ? 1 : 0,
363
- 'AJAX_URL'=>admin_url('admin-ajax.php'),
364
- 'BULK_SECRET' => $secretKey,
365
- 'nonce_ajaxrequest' => wp_create_nonce('ajax_request'),
366
- 'HAS_QUOTA' => ($quotaController->hasQuota()) ? 1 : 0,
367
-
368
- ));
369
-
370
- if (Log::isManualDebug() )
371
- {
372
- Log::addInfo('Ajax Manual Debug Mode');
373
- $logLevel = Log::getLogLevel();
374
- $ShortPixelConstants[0]['AJAX_URL'] = admin_url('admin-ajax.php?SHORTPIXEL_DEBUG=' . $logLevel);
375
- }
376
-
377
- $jsTranslation = array(
378
- 'optimizeWithSP' => __( 'Optimize with ShortPixel', 'shortpixel-image-optimiser' ),
379
- 'redoLossy' => __( 'Re-optimize Lossy', 'shortpixel-image-optimiser' ),
380
- 'redoGlossy' => __( 'Re-optimize Glossy', 'shortpixel-image-optimiser' ),
381
- 'redoLossless' => __( 'Re-optimize Lossless', 'shortpixel-image-optimiser' ),
382
- 'restoreOriginal' => __( 'Restore Originals', 'shortpixel-image-optimiser' ),
383
- 'changeMLToListMode' => __( 'In order to access the ShortPixel Optimization actions and info, please change to {0}List View{1}List View{2}Dismiss{3}', 'shortpixel-image-optimiser' ),
384
- 'alertOnlyAppliesToNewImages' => __( 'This type of optimization will apply to new uploaded images. Images that were already processed will not be re-optimized unless you restart the bulk process.', 'shortpixel-image-optimiser' ),
385
- 'areYouSureStopOptimizing' => __( 'Are you sure you want to stop optimizing the folder {0}?', 'shortpixel-image-optimiser' ),
386
- 'reducedBy' => __( 'Reduced by', 'shortpixel-image-optimiser' ),
387
- 'bonusProcessing' => __( 'Bonus processing', 'shortpixel-image-optimiser' ),
388
- 'plusXthumbsOpt' => __( '+{0} thumbnails optimized', 'shortpixel-image-optimiser' ),
389
- 'plusXretinasOpt' => __( '+{0} Retina images optimized', 'shortpixel-image-optimiser' ),
390
- 'optXThumbs' => __( 'Optimize {0} thumbnails', 'shortpixel-image-optimiser' ),
391
- 'reOptimizeAs' => __( 'Reoptimize {0}', 'shortpixel-image-optimiser' ),
392
- 'restoreBackup' => __( 'Restore backup', 'shortpixel-image-optimiser' ),
393
- 'getApiKey' => __( 'Get API Key', 'shortpixel-image-optimiser' ),
394
- 'extendQuota' => __( 'Extend Quota', 'shortpixel-image-optimiser' ),
395
- 'check__Quota' => __( 'Check&nbsp;&nbsp;Quota', 'shortpixel-image-optimiser' ),
396
- 'retry' => __( 'Retry', 'shortpixel-image-optimiser' ),
397
- 'thisContentNotProcessable' => __( 'This content is not processable.', 'shortpixel-image-optimiser' ),
398
- 'imageWaitOptThumbs' => __( 'Image waiting to optimize thumbnails', 'shortpixel-image-optimiser' ),
399
- 'pleaseDoNotSetLesserSize' => __( "Please do not set a {0} less than the {1} of the largest thumbnail which is {2}, to be able to still regenerate all your thumbnails in case you'll ever need this.", 'shortpixel-image-optimiser' ),
400
- 'pleaseDoNotSetLesser1024' => __( "Please do not set a {0} less than 1024, to be able to still regenerate all your thumbnails in case you'll ever need this.", 'shortpixel-image-optimiser' ),
401
- 'confirmBulkRestore' => __( "Are you sure you want to restore from backup all the images in your Media Library optimized with ShortPixel?", 'shortpixel-image-optimiser' ),
402
- 'confirmBulkCleanup' => __( "Are you sure you want to cleanup the ShortPixel metadata info for the images in your Media Library optimized with ShortPixel? This will make ShortPixel 'forget' that it optimized them and will optimize them again if you re-run the Bulk Optimization process.", 'shortpixel-image-optimiser' ),
403
- 'confirmBulkCleanupPending' => __( "Are you sure you want to cleanup the pending metadata?", 'shortpixel-image-optimiser' ),
404
- 'alertDeliverWebPAltered' => __( "Warning: Using this method alters the structure of the rendered HTML code (IMG tags get included in PICTURE tags), which, in some rare \ncases, can lead to CSS/JS inconsistencies.\n\nPlease test this functionality thoroughly after activating!\n\nIf you notice any issue, just deactivate it and the HTML will will revert to the previous state.", 'shortpixel-image-optimiser' ),
405
- 'alertDeliverWebPUnaltered' => __('This option will serve both WebP and the original image using the same URL, based on the web browser capabilities, please make sure you\'re serving the images from your server and not using a CDN which caches the images.', 'shortpixel-image-optimiser' ),
406
- 'originalImage' => __('Original image', 'shortpixel-image-optimiser' ),
407
- 'optimizedImage' => __('Optimized image', 'shortpixel-image-optimiser' ),
408
- 'loading' => __('Loading...', 'shortpixel-image-optimiser' ),
409
- //'' => __('', 'shortpixel-image-optimiser' ),
410
- );
411
-
412
- /*$actions = array(
413
- 'nonce_check_quota' => wp_create_nonce('check_quota')
414
- ); */
415
- wp_localize_script( 'shortpixel', '_spTr', $jsTranslation );
416
- wp_localize_script( 'shortpixel', 'ShortPixelConstants', $ShortPixelConstants );
417
- //wp_localize_script('shortpixel', 'ShortPixelActions', $actions);
418
-
419
 
420
- /* if (! \wpSPIO()->env()->is_screen_to_use )
421
- {
422
- if (! wpSPIO()->env()->is_front) // exeception if this is called to load from your frontie.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
423
  return; // not ours, don't load JS and such.
424
- } */
425
-
426
-
427
- }
428
-
429
- public function admin_styles()
430
- {
431
-
432
- wp_register_style('sp-file-tree', plugins_url('/res/css/sp-file-tree.min.css',SHORTPIXEL_PLUGIN_FILE),array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION );
433
-
434
- wp_register_style('shortpixel', plugins_url('/res/css/short-pixel.css',SHORTPIXEL_PLUGIN_FILE), array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION);
435
-
436
- // notices. additional styles for SPIO.
437
- wp_register_style('shortpixel-notices', plugins_url('/res/css/shortpixel-notices.css',SHORTPIXEL_PLUGIN_FILE), array('shortpixel-admin'), SHORTPIXEL_IMAGE_OPTIMISER_VERSION);
438
-
439
- // other media screen
440
- wp_register_style('shortpixel-othermedia', plugins_url('/res/css/shortpixel-othermedia.css',SHORTPIXEL_PLUGIN_FILE), array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION);
441
 
442
- // load everywhere, because we are inconsistent.
443
- wp_register_style('shortpixel-toolbar', plugins_url('/res/css/shortpixel-toolbar.css',SHORTPIXEL_PLUGIN_FILE), array('dashicons'), SHORTPIXEL_IMAGE_OPTIMISER_VERSION);
444
-
445
- // @todo Might need to be removed later on
446
- wp_register_style('shortpixel-admin', plugins_url('/res/css/shortpixel-admin.css', SHORTPIXEL_PLUGIN_FILE),array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION );
447
-
448
- wp_register_style('shortpixel-bulk', plugins_url('/res/css/shortpixel-bulk.css', SHORTPIXEL_PLUGIN_FILE),array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION );
449
-
450
- wp_register_style('shortpixel-nextgen', plugins_url('/res/css/shortpixel-nextgen.css', SHORTPIXEL_PLUGIN_FILE),array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION );
451
 
452
- wp_register_style('shortpixel-settings', plugins_url('/res/css/shortpixel-settings.css', SHORTPIXEL_PLUGIN_FILE),array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION );
453
 
454
- }
455
 
 
456
 
457
- /** Load Style via Route, on demand */
458
- public function load_style($name)
459
- {
460
- if ($this->is_noheaders) // fail silently, if this is a no-headers request.
461
- return;
462
 
463
- if (wp_style_is($name, 'registered'))
464
- {
465
- wp_enqueue_style($name);
466
- }
467
- else {
468
- Log::addWarn("Style $name was asked for, but not registered");
469
- }
470
- }
471
 
472
- /** Load Style via Route, on demand */
473
- public function load_script($script)
474
- {
475
- if ($this->is_noheaders) // fail silently, if this is a no-headers request.
476
- return;
477
 
478
- if (! is_array($script))
479
- $script = array($script);
480
 
481
- foreach($script as $index => $name)
482
- {
483
- if (wp_script_is($name, 'registered'))
484
- {
485
- wp_enqueue_script($name);
486
- }
487
- else {
488
- Log::addWarn("Script $name was asked for, but not registered");
489
- }
490
- }
491
- }
492
 
493
- /** This is separated from route to load in head, preventing unstyled content all the time */
494
- public function load_admin_scripts($hook_suffix)
495
- {
496
- global $plugin_page;
497
- $screen_id = \wpSPIO()->env()->screen_id;
498
 
499
- //$load = array();
500
- $load_processor = array('shortpixel', 'shortpixel-processor'); // a whole suit needed for processing, not more. Always needs a screen as well!
501
- $load_bulk = array(); // the whole suit needed for bulking.
502
 
 
503
 
504
- if ($this->env()->is_debug)
505
- {
506
- $this->load_script('shortpixel-debug');
507
- }
508
 
 
 
 
 
 
509
 
510
- if ( \wpSPIO()->env()->is_screen_to_use )
511
- {
512
- $this->load_script('shortpixel-tooltip');
513
- $this->load_style('shortpixel-toolbar');
 
 
514
 
515
- }
 
 
 
 
516
 
517
- if ($plugin_page == 'wp-shortpixel-settings')
518
- {
519
- $this->load_script($load_processor);
520
- $this->load_script('shortpixel-screen-nolist'); // screen
521
- $this->load_script('jquery.tooltip.min.js');
522
- $this->load_script('sp-file-tree');
523
- $this->load_script('shortpixel-settings');
524
 
 
 
 
 
 
 
 
 
525
 
526
- $this->load_style('shortpixel-admin');
527
- $this->load_style('shortpixel');
528
- $this->load_style('sp-file-tree');
529
- $this->load_style('shortpixel-settings');
530
 
 
 
531
 
532
- }
533
- elseif ($plugin_page == 'wp-short-pixel-bulk')
534
- {
535
- $this->load_script($load_processor);
536
- $this->load_script('shortpixel-screen-bulk');
537
 
538
- $this->load_style('shortpixel-admin');
539
- $this->load_style('shortpixel-bulk');
540
- }
541
- elseif ($screen_id == 'upload' || $screen_id == 'attachment')
542
- {
543
- $this->load_script($load_processor);
544
- $this->load_script('shortpixel-screen-media'); // screen
545
 
546
- $this->load_style('shortpixel-admin');
547
- $this->load_style('shortpixel');
 
548
 
549
- }
550
- elseif ($plugin_page == 'wp-short-pixel-custom')
551
- {
552
- $this->load_style('shortpixel');
553
- $this->load_style('shortpixel-admin');
554
 
555
- $this->load_style('shortpixel-othermedia');
 
 
 
 
 
556
 
 
 
 
 
557
 
558
- $this->load_script($load_processor);
559
- $this->load_script('shortpixel-screen-custom'); // screen
 
560
 
561
- }
562
- elseif(NextGenController::getInstance()->isNextGenScreen())
563
- {
564
- $this->load_script($load_processor);
565
- $this->load_script('shortpixel-screen-custom'); // screen
566
- $this->load_style('shortpixel-admin');
567
 
568
- $this->load_style('shortpixel');
569
- $this->load_style('shortpixel-nextgen');
570
 
571
- }
 
 
572
 
 
573
 
574
- }
 
575
 
576
- /** Route, based on the page slug
577
- *
578
- * Principially all page controller should be routed from here.
579
- */
580
- public function route()
581
- {
582
- global $plugin_page;
583
- // $this->initPluginRunTime(); // Not in use currently.
584
- $default_action = 'load'; // generic action on controller.
585
- $action = isset($_REQUEST['sp-action']) ? sanitize_text_field($_REQUEST['sp-action']) : $default_action;
586
- $template_part = isset($_GET['part']) ? sanitize_text_field($_GET['part']) : false;
587
 
588
- $controller = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
589
 
590
- $url = menu_page_url($plugin_page, false);
591
- $screen_id = \wpSPIO()->env()->screen_id;
592
 
593
- switch($plugin_page)
594
- {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
595
  case 'wp-shortpixel-settings': // settings
596
- $controller = 'ShortPixel\Controller\SettingsController';
597
- break;
598
  case 'wp-short-pixel-custom': // other media
599
- /* $this->load_style('shortpixel-othermedia'); */
600
- $controller = 'ShortPixel\Controller\View\OtherMediaViewController';
601
- break;
602
- case 'wp-short-pixel-bulk':
603
- if ($template_part)
604
- {
605
- switch($template_part)
606
- {
607
- case 'bulk-restore-all':
608
- $controller = '\ShortPixel\Controller\View\BulkRestoreAll';
609
- break;
610
- }
611
- }
612
- else
613
- $controller = '\ShortPixel\Controller\View\BulkViewController';
614
- break;
615
  case null:
616
  default:
617
- switch($screen_id)
618
- {
619
- case 'upload':
620
  $controller = '\ShortPixel\Controller\View\ListMediaViewController';
621
- break;
622
- case 'attachment'; // edit-media
623
  $controller = '\ShortPixel\Controller\View\EditMediaViewController';
624
  break;
625
 
626
  }
627
- break;
 
 
628
 
 
 
 
 
 
 
 
 
 
 
 
629
 
630
- }
631
 
632
- if ($controller !== false)
633
- {
634
- $c = new $controller();
635
- $c->setControllerURL($url);
636
- if (method_exists($c, $action))
637
- $c->$action();
638
- else {
639
- Log::addWarn("Attempted Action $action on $controller does not exist!");
640
- $c->$default_action();
641
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
642
 
643
- }
644
- }
645
-
646
-
647
- // Get the plugin URL, based on real URL.
648
- public function plugin_url($urlpath = '')
649
- {
650
- $url = trailingslashit($this->plugin_url);
651
- if (strlen($urlpath) > 0)
652
- $url .= $urlpath;
653
- return $url;
654
- }
655
-
656
- // Get the plugin path.
657
- public function plugin_path($path = '')
658
- {
659
- $plugin_path = trailingslashit($this->plugin_path);
660
- if (strlen($path) > 0)
661
- $plugin_path .= $path;
662
-
663
- return $plugin_path;
664
- }
665
-
666
- /** Returns defined admin page hooks. Internal use - check states via environmentmodel
667
- * @returns Array
668
- */
669
- public function get_admin_pages()
670
- {
671
- return $this->admin_pages;
672
- }
673
-
674
- protected function check_plugin_version()
675
- {
676
- $version = SHORTPIXEL_IMAGE_OPTIMISER_VERSION;
677
  $db_version = $this->settings()->currentVersion;
678
 
679
- if ($version !== $db_version)
680
- {
681
- InstallHelper::activatePlugin();
682
- }
683
  $this->settings()->currentVersion = $version;
684
  }
685
 
1
  <?php
2
  namespace ShortPixel;
3
+
4
  use ShortPixel\ShortpixelLogger\ShortPixelLogger as Log;
5
  use ShortPixel\Notices\NoticeController as Notices;
6
  use ShortPixel\Controller\OptimizeController as OptimizeController;
10
  use ShortPixel\Controller\OtherMediaController as OtherMediaController;
11
  use ShortPixel\NextGenController as NextGenController;
12
 
13
+ // use ShortPixel\Controller;
14
 
15
  use ShortPixel\Controller\Queue\MediaLibraryQueue as MediaLibraryQueue;
16
  use ShortPixel\Controller\Queue\CustomQueue as CustomQueue;
18
  use ShortPixel\Helper\InstallHelper as InstallHelper;
19
 
20
  /** Plugin class
21
+ * This class is meant for: WP Hooks, init of runtime and Controller Routing.
22
+ */
23
+ class ShortPixelPlugin {
 
 
 
 
 
 
24
 
25
+ private static $instance;
26
+ protected static $modelsLoaded = array(); // don't require twice, limit amount of require looksups..
27
 
28
+ // private $paths = array('class', 'class/controller', 'class/external', 'class/controller/views'); // classes that are autoloaded
 
29
 
30
+ protected $is_noheaders = false;
 
31
 
32
+ protected $plugin_path;
33
+ protected $plugin_url;
34
 
35
+ protected $shortPixel; // shortpixel megaclass
36
+ protected $settings; // settings object.
 
 
37
 
38
+ protected $admin_pages = array(); // admin page hooks.
 
 
39
 
40
+ public function __construct() {
41
+ $this->plugin_path = plugin_dir_path( SHORTPIXEL_PLUGIN_FILE );
42
+ $this->plugin_url = plugin_dir_url( SHORTPIXEL_PLUGIN_FILE );
43
 
44
+ // $this->initHooks();
45
+ add_action( 'plugins_loaded', array( $this, 'lowInit' ), 5 ); // early as possible init.
46
+ }
 
 
 
47
 
 
 
 
48
 
49
+ /** LowInit after all Plugins are loaded. Core WP function can still be missing. This should mostly add hooks */
50
+ public function lowInit() {
51
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is not a form
52
+ if ( isset( $_REQUEST['noheader'] ) ) {
53
+ $this->is_noheaders = true;
54
+ }
55
 
56
+ /*
57
+ Filter to prevent SPIO from starting. This can be used by third-parties to prevent init when needed for a particular situation.
58
+ * Hook into plugins_loaded with priority lower than 5 */
59
+ $init = apply_filters( 'shortpixel/plugin/init', true );
60
 
61
+ if ( ! $init ) {
62
+ return;
63
+ }
64
 
65
+ $front = new Controller\FrontController();
66
+ $admin = Controller\AdminController::getInstance();
67
+ $adminNotices = Controller\AdminNoticesController::getInstance(); // Hook in the admin notices.
68
 
69
+ $this->initHooks();
70
+ $this->ajaxHooks();
71
 
72
  if ( defined( 'WP_CLI' ) && WP_CLI ) {
73
+ WPCliController::getInstance();
74
  }
75
 
76
+ add_action( 'admin_init', array( $this, 'init' ) );
77
+ }
78
 
79
 
80
+ /** Mainline Admin Init. Tasks that can be loaded later should go here */
81
+ public function init() {
 
82
  // This runs activation thing. Should be -after- init
83
  $this->check_plugin_version();
84
 
85
+ $notices = Notices::getInstance(); // This hooks the ajax listener
86
  $quotaController = QuotaController::getInstance();
87
  $quotaController->getQuota();
88
 
89
+ }
90
 
91
+ /** Function to get plugin settings
92
+ *
93
+ * @return SettingsModel The settings model object.
94
+ */
95
+ public function settings() {
96
+ if ( is_null( $this->settings ) ) {
97
+ $this->settings = new \WPShortPixelSettings();
98
+ }
 
 
 
 
 
99
 
100
+ return $this->settings;
101
+ }
 
 
 
 
 
 
102
 
103
+ /** Function to get all enviromental variables
104
+ *
105
+ * @return EnvironmentModel
106
+ */
107
+ public function env() {
108
+ return Model\EnvironmentModel::getInstance();
109
+ }
110
 
111
+ public function fileSystem() {
112
+ return new Controller\FileSystemController();
113
+ }
 
 
 
 
 
 
 
114
 
115
+ /** Create instance. This should not be needed to call anywhere else than main plugin file
116
+ * This should not be called *after* plugins_loaded action
117
+ **/
118
+ public static function getInstance() {
119
+ if ( is_null( self::$instance ) ) {
120
+ self::$instance = new ShortPixelPlugin();
121
+ }
122
+ return self::$instance;
123
 
124
+ }
125
 
 
 
 
 
 
 
 
 
 
 
126
 
127
+ /** Hooks for all WordPress related hooks
128
+ * For now hooks in the lowInit, asap.
129
+ */
130
+ public function initHooks() {
131
+ add_action( 'admin_menu', array( $this, 'admin_pages' ) );
132
+ add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) ); // admin scripts
133
+ add_action( 'admin_enqueue_scripts', array( $this, 'admin_styles' ) ); // admin styles
134
+ add_action( 'admin_enqueue_scripts', array( $this, 'load_admin_scripts' ), 90 ); // loader via route.
135
+ add_action( 'enqueue_block_assets', array($this, 'load_admin_scripts'), 90);
136
+ // defer notices a little to allow other hooks ( notable adminnotices )
137
 
138
+ $optimizeController = new OptimizeController();
139
+ add_action( 'shortpixel-thumbnails-regenerated', array( $optimizeController, 'thumbnailsChangedHook' ), 10, 4 );
140
 
141
+ // Media Library
142
+ add_action( 'load-upload.php', array( $this, 'route' ) );
143
 
144
+ add_action( 'load-post.php', array( $this, 'route' ) );
145
 
146
+ $admin = AdminController::getInstance();
147
 
148
+ // Handle for EMR
149
+ add_action( 'wp_handle_replace', array( $admin, 'handleReplaceHook' ) );
150
 
151
  // Action / hook for who wants to use CRON. Please refer to manual / support to prevent loss of credits.
152
+ add_action( 'shortpixel/hook/processqueue', array( $admin, 'processQueueHook' ) );
153
 
154
+ if ( $this->env()->is_autoprocess ) {
155
+ // compat filter to shortcircuit this in cases. (see external - visualcomposer)
156
+ if ( apply_filters( 'shortpixel/init/automedialibrary', true ) ) {
157
+ if ( $this->settings()->png2jpg ) {
 
 
 
158
 
159
  /*
160
  This processing off because it doesn't make sense to already start this before optimizing, which will happen via queue.
161
+ add_action( 'add_attachment', array($admin,'handlePng2JpgHook'));
162
+ add_action( 'wp_handle_upload', array($admin,'handlePng2JpgHook'));
163
 
164
+ // @integration MediaPress
165
+ add_action( 'mpp_handle_upload', array($admin,'handlePng2JpgHook'));
166
  */
167
+ }
 
 
 
 
168
 
169
+ add_action( 'shortpixel-thumbnails-before-regenerate', array( $admin, 'preventImageHook' ), 10, 1 );
 
 
 
 
170
 
171
+ add_action( 'enable-media-replace-upload-done', array( $admin, 'handleReplaceEnqueue' ), 10, 3 );
172
 
173
+ add_filter( 'wp_generate_attachment_metadata', array( $admin, 'handleImageUploadHook' ), 10, 2 );
174
+ // @integration MediaPress
175
+ add_filter( 'mpp_generate_metadata', array( $admin, 'handleImageUploadHook' ), 10, 2 );
176
+ }
177
+ }
178
 
179
+ load_plugin_textdomain( 'shortpixel-image-optimiser', false, plugin_basename( dirname( SHORTPIXEL_PLUGIN_FILE ) ) . '/lang' );
180
 
181
+ $isAdminUser = current_user_can( 'manage_options' ); // @todo This should be in env
182
 
183
+ $this->env()->setDefaultViewModeList();// set default mode as list. only @ first run
 
 
184
 
185
+ add_filter( 'plugin_action_links_' . plugin_basename( SHORTPIXEL_PLUGIN_FILE ), array( $admin, 'generatePluginLinks' ) );// for plugin settings page
 
186
 
187
+ // for cleaning up the WebP images when an attachment is deleted
188
+ add_action( 'delete_attachment', array( $admin, 'onDeleteAttachment' ) );
189
+ add_action( 'mime_types', array( $admin, 'addMimes' ) );
190
 
191
+ // integration with WP/LR Sync plugin
192
+ add_action( 'wplr_update_media', array( AjaxController::getInstance(), 'onWpLrUpdateMedia' ), 10, 2 );
193
 
194
+ add_action( 'admin_bar_menu', array( $admin, 'toolbar_shortpixel_processing' ), 999 );
 
 
195
 
196
+ if ( $isAdminUser ) {
197
+ // toolbar notifications
198
+ // add_action( 'wp_head', array( $this, 'headCSS')); // for the front-end
199
 
200
+ // deactivate conflicting plugins if found
201
+ add_action( 'admin_post_shortpixel_deactivate_conflict_plugin', array( '\ShortPixel\Helper\InstallHelper', 'deactivateConflictingPlugin' ) );
 
 
 
 
 
 
 
 
202
 
203
+ // only if the key is not yet valid or the user hasn't bought any credits.
204
+ // @todo This should not be done here.
205
+ $settings = $this->settings();
206
+ $stats = $settings->currentStats;
207
+ $totalCredits = isset( $stats['APICallsQuotaNumeric'] ) ? $stats['APICallsQuotaNumeric'] + $stats['APICallsQuotaOneTimeNumeric'] : 0;
208
+ if ( true || ! $settings->verifiedKey || $totalCredits < 4000 ) {
209
+ require_once 'class/view/shortpixel-feedback.php';
210
+ new ShortPixelFeedback( SHORTPIXEL_PLUGIN_FILE, 'shortpixel-image-optimiser' );
211
+ }
212
+ }
213
 
214
+ }
215
 
216
+ protected function ajaxHooks() {
 
217
 
218
+ // Ajax hooks. Should always be prepended with ajax_ and *must* check on nonce in function
219
+ add_action( 'wp_ajax_shortpixel_image_processing', array( AjaxController::getInstance(), 'ajax_processQueue' ) );
220
 
221
+ // Custom Media
222
+ add_action( 'wp_ajax_shortpixel_browse_content', array( OtherMediaController::getInstance(), 'ajaxBrowseContent' ) );
223
+ add_action( 'wp_ajax_shortpixel_get_backup_size', array( AjaxController::getInstance(), 'ajax_getBackupFolderSize' ) );
224
 
225
+ add_action( 'wp_ajax_shortpixel_propose_upgrade', array( AjaxController::getInstance(), 'ajax_proposeQuotaUpgrade' ) );
226
+ add_action( 'wp_ajax_shortpixel_check_quota', array( AjaxController::getInstance(), 'ajax_checkquota' ) );
227
 
228
+ // @todo should probably go through ajaxrequest.
229
+ add_action( 'wp_ajax_shortpixel_get_comparer_data', array( AjaxController::getInstance(), 'ajax_getComparerData' ) );
230
 
231
+ add_action( 'wp_ajax_shortpixel_ajaxRequest', array( AjaxController::getInstance(), 'ajaxRequest' ) );
232
 
233
  // Used by processor
234
+ add_action( 'wp_ajax_shortpixel_get_item_view', array( AjaxController::getInstance(), 'ajax_getItemView' ) );
 
 
235
 
236
+ }
 
 
 
 
 
237
 
238
+ /** Hook in our admin pages */
239
+ public function admin_pages() {
240
+ $admin_pages = array();
241
+ // settings page
242
+ $admin_pages[] = add_options_page( __( 'ShortPixel Settings', 'shortpixel-image-optimiser' ), 'ShortPixel', 'manage_options', 'wp-shortpixel-settings', array( $this, 'route' ) );
 
 
 
243
 
244
+ $otherMediaController = OtherMediaController::getInstance();
245
+ if ( $otherMediaController->hasCustomImages() ) {
246
+ /*translators: title and menu name for the Other media page*/
247
+ $admin_pages[] = add_media_page( __( 'Custom Media Optimized by ShortPixel', 'shortpixel-image-optimiser' ), __( 'Custom Media', 'shortpixel-image-optimiser' ), 'edit_others_posts', 'wp-short-pixel-custom', array( $this, 'route' ) );
248
+ }
249
+ /*translators: title and menu name for the Bulk Processing page*/
250
+ $admin_pages[] = add_media_page( __( 'ShortPixel Bulk Process', 'shortpixel-image-optimiser' ), __( 'Bulk ShortPixel', 'shortpixel-image-optimiser' ), 'edit_others_posts', 'wp-short-pixel-bulk', array( $this, 'route' ) );
251
 
252
+ $this->admin_pages = $admin_pages;
253
+ }
254
 
 
 
 
 
 
 
255
 
256
+ /** All scripts should be registed, not enqueued here (unless global wp-admin is needed )
257
+ *
258
+ * Not all those registered must be enqueued however.
259
+ */
260
+ public function admin_scripts( $hook_suffix ) {
261
 
262
+ $settings = \wpSPIO()->settings();
263
+ $ajaxController = AjaxController::getInstance();
264
 
265
+ $secretKey = $ajaxController->getProcessorKey();
 
266
 
267
+ $keyControl = \ShortPixel\Controller\ApiKeyController::getInstance();
268
+ $apikey = $keyControl->getKeyForDisplay();
269
 
270
+ $is_bulk_page = \wpSPIO()->env()->is_bulk_page;
 
271
 
272
+ $optimizeController = new OptimizeController();
273
+ $optimizeController->setBulk( $is_bulk_page );
274
 
275
+ $quotaController = QuotaController::getInstance();
276
 
277
+ // FileTree in Settings
278
+ wp_register_script( 'sp-file-tree', plugins_url( '/res/js/sp-file-tree.min.js', SHORTPIXEL_PLUGIN_FILE ), array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true );
279
 
280
+ wp_register_script( 'jquery.knob.min.js', plugins_url( '/res/js/jquery.knob.min.js', SHORTPIXEL_PLUGIN_FILE ), array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true );
281
 
282
+ wp_register_script( 'jquery.tooltip.min.js', plugins_url( '/res/js/jquery.tooltip.min.js', SHORTPIXEL_PLUGIN_FILE ), array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true );
283
 
284
+ wp_register_script( 'shortpixel-debug', plugins_url( '/res/js/debug.js', SHORTPIXEL_PLUGIN_FILE ), array( 'jquery', 'jquery-ui-draggable' ), SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true );
285
 
286
+ wp_register_script( 'shortpixel-tooltip', plugins_url( '/res/js/shortpixel-tooltip.js', SHORTPIXEL_PLUGIN_FILE ), array( 'jquery' ), SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true );
287
+ wp_register_script( 'shortpixel-settings', plugins_url( 'res/js/shortpixel-settings.js', SHORTPIXEL_PLUGIN_FILE ), array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true );
288
 
289
+ wp_register_script( 'shortpixel-processor', plugins_url( '/res/js/shortpixel-processor.js', SHORTPIXEL_PLUGIN_FILE ), array( 'jquery', 'shortpixel-tooltip' ), SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true );
290
 
291
  // How often JS processor asks for next tick on server. Low for fastestness and high loads, high number for surviving servers.
292
+ $interval = apply_filters( 'shortpixel/processor/interval', 3000 );
293
 
294
  // If the queue is empty how often to check if something new appeared from somewhere. Excluding the manual items added by current processor user.
295
+ $deferInterval = apply_filters( 'shortpixel/process/deferInterval', 60000 );
296
 
297
+ wp_localize_script(
298
+ 'shortpixel-processor',
299
+ 'ShortPixelProcessorData',
300
+ array(
301
+ 'bulkSecret' => $secretKey,
302
+ 'isBulkPage' => (bool) $is_bulk_page,
303
+ 'screenURL' => false,
304
+ 'workerURL' => $this->plugin_url( 'res/js/shortpixel-worker.js' ),
305
+ 'nonce_process' => wp_create_nonce( 'processing' ),
306
+ 'nonce_exit' => wp_create_nonce( 'exit_process' ),
307
+ 'nonce_itemview' => wp_create_nonce( 'item_view' ),
308
+ 'nonce_ajaxrequest' => wp_create_nonce( 'ajax_request' ),
309
+ 'startData' => ( \wpSPIO()->env()->is_screen_to_use ) ? $optimizeController->getStartupData() : false,
310
+ 'interval' => $interval,
311
+ 'deferInterval' => $deferInterval,
312
 
313
+ )
314
+ );
315
 
316
+ /*** SCREENS */
317
+ wp_register_script( 'shortpixel-screen-media', plugins_url( '/res/js/screens/screen-media.js', SHORTPIXEL_PLUGIN_FILE ), array( 'jquery', 'shortpixel-processor' ), SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true );
318
 
319
+ wp_register_script( 'shortpixel-screen-custom', plugins_url( '/res/js/screens/screen-custom.js', SHORTPIXEL_PLUGIN_FILE ), array( 'jquery', 'shortpixel-processor' ), SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true );
320
 
321
+ wp_register_script( 'shortpixel-screen-nolist', plugins_url( '/res/js/screens/screen-nolist.js', SHORTPIXEL_PLUGIN_FILE ), array( 'jquery', 'shortpixel-processor' ), SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true );
322
 
323
+ wp_register_script( 'shortpixel-screen-bulk', plugins_url( '/res/js/screens/screen-bulk.js', SHORTPIXEL_PLUGIN_FILE ), array( 'jquery', 'shortpixel-processor' ), SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true );
324
 
325
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is not a form
326
+ $panel = isset( $_GET['panel'] ) ? sanitize_text_field( wp_unslash($_GET['panel']) ) : false;
327
 
328
  $bulkLocalize = array(
329
+ 'endBulk' => __( 'This will stop the bulk processing and take you back to the start. Are you sure you want to do this?', 'shortpixel-image-optimiser' ),
330
+ 'reloadURL' => admin_url( 'upload.php?page=wp-short-pixel-bulk' ),
331
+ );
332
+ if ( $panel ) {
333
  $bulkLocalize['panel'] = $panel;
334
+ }
335
 
336
+ // screen translations. Can all be loaded on the same var, since only one screen can be active.
337
+ wp_localize_script( 'shortpixel-screen-bulk', 'shortPixelScreen', $bulkLocalize );
338
+
339
+ wp_register_script( 'shortpixel', plugins_url( '/res/js/shortpixel.js', SHORTPIXEL_PLUGIN_FILE ), array( 'jquery', 'jquery.knob.min.js' ), SHORTPIXEL_IMAGE_OPTIMISER_VERSION, true );
340
+
341
+ // Using an Array within another Array to protect the primitive values from being cast to strings
342
+ $ShortPixelConstants = array(
343
+ array(
344
+ 'WP_PLUGIN_URL' => plugins_url( '', SHORTPIXEL_PLUGIN_FILE ),
345
+ 'WP_ADMIN_URL' => admin_url(),
346
+ 'API_IS_ACTIVE' => $keyControl->keyIsVerified(),
347
+ 'FRONT_BOOTSTRAP' => $settings->frontBootstrap && ( ! isset( $settings->lastBackAction ) || ( time() - $settings->lastBackAction > 600 ) ) ? 1 : 0,
348
+ 'AJAX_URL' => admin_url( 'admin-ajax.php' ),
349
+ 'BULK_SECRET' => $secretKey,
350
+ 'nonce_ajaxrequest' => wp_create_nonce( 'ajax_request' ),
351
+ 'HAS_QUOTA' => ( $quotaController->hasQuota() ) ? 1 : 0,
352
+
353
+ ),
354
+ );
355
+
356
+ if ( Log::isManualDebug() ) {
357
+ Log::addInfo( 'Ajax Manual Debug Mode' );
358
+ $logLevel = Log::getLogLevel();
359
+ $ShortPixelConstants[0]['AJAX_URL'] = admin_url( 'admin-ajax.php?SHORTPIXEL_DEBUG=' . $logLevel );
360
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
361
 
362
+ $jsTranslation = array(
363
+ 'optimizeWithSP' => __( 'Optimize with ShortPixel', 'shortpixel-image-optimiser' ),
364
+ 'redoLossy' => __( 'Re-optimize Lossy', 'shortpixel-image-optimiser' ),
365
+ 'redoGlossy' => __( 'Re-optimize Glossy', 'shortpixel-image-optimiser' ),
366
+ 'redoLossless' => __( 'Re-optimize Lossless', 'shortpixel-image-optimiser' ),
367
+ 'restoreOriginal' => __( 'Restore Originals', 'shortpixel-image-optimiser' ),
368
+ 'changeMLToListMode' => __( 'In order to access the ShortPixel Optimization actions and info, please change to {0}List View{1}List View{2}Dismiss{3}', 'shortpixel-image-optimiser' ),
369
+ 'alertOnlyAppliesToNewImages' => __( 'This type of optimization will apply to new uploaded images. Images that were already processed will not be re-optimized unless you restart the bulk process.', 'shortpixel-image-optimiser' ),
370
+ 'areYouSureStopOptimizing' => __( 'Are you sure you want to stop optimizing the folder {0}?', 'shortpixel-image-optimiser' ),
371
+ 'reducedBy' => __( 'Reduced by', 'shortpixel-image-optimiser' ),
372
+ 'bonusProcessing' => __( 'Bonus processing', 'shortpixel-image-optimiser' ),
373
+ 'plusXthumbsOpt' => __( '+{0} thumbnails optimized', 'shortpixel-image-optimiser' ),
374
+ 'plusXretinasOpt' => __( '+{0} Retina images optimized', 'shortpixel-image-optimiser' ),
375
+ 'optXThumbs' => __( 'Optimize {0} thumbnails', 'shortpixel-image-optimiser' ),
376
+ 'reOptimizeAs' => __( 'Reoptimize {0}', 'shortpixel-image-optimiser' ),
377
+ 'restoreBackup' => __( 'Restore backup', 'shortpixel-image-optimiser' ),
378
+ 'getApiKey' => __( 'Get API Key', 'shortpixel-image-optimiser' ),
379
+ 'extendQuota' => __( 'Extend Quota', 'shortpixel-image-optimiser' ),
380
+ 'check__Quota' => __( 'Check&nbsp;&nbsp;Quota', 'shortpixel-image-optimiser' ),
381
+ 'retry' => __( 'Retry', 'shortpixel-image-optimiser' ),
382
+ 'thisContentNotProcessable' => __( 'This content is not processable.', 'shortpixel-image-optimiser' ),
383
+ 'imageWaitOptThumbs' => __( 'Image waiting to optimize thumbnails', 'shortpixel-image-optimiser' ),
384
+ 'pleaseDoNotSetLesserSize' => __( "Please do not set a {0} less than the {1} of the largest thumbnail which is {2}, to be able to still regenerate all your thumbnails in case you'll ever need this.", 'shortpixel-image-optimiser' ),
385
+ 'pleaseDoNotSetLesser1024' => __( "Please do not set a {0} less than 1024, to be able to still regenerate all your thumbnails in case you'll ever need this.", 'shortpixel-image-optimiser' ),
386
+ 'confirmBulkRestore' => __( 'Are you sure you want to restore from backup all the images in your Media Library optimized with ShortPixel?', 'shortpixel-image-optimiser' ),
387
+ 'confirmBulkCleanup' => __( "Are you sure you want to cleanup the ShortPixel metadata info for the images in your Media Library optimized with ShortPixel? This will make ShortPixel 'forget' that it optimized them and will optimize them again if you re-run the Bulk Optimization process.", 'shortpixel-image-optimiser' ),
388
+ 'confirmBulkCleanupPending' => __( 'Are you sure you want to cleanup the pending metadata?', 'shortpixel-image-optimiser' ),
389
+ 'alertDeliverWebPAltered' => __( "Warning: Using this method alters the structure of the rendered HTML code (IMG tags get included in PICTURE tags), which, in some rare \ncases, can lead to CSS/JS inconsistencies.\n\nPlease test this functionality thoroughly after activating!\n\nIf you notice any issue, just deactivate it and the HTML will will revert to the previous state.", 'shortpixel-image-optimiser' ),
390
+ 'alertDeliverWebPUnaltered' => __( 'This option will serve both WebP and the original image using the same URL, based on the web browser capabilities, please make sure you\'re serving the images from your server and not using a CDN which caches the images.', 'shortpixel-image-optimiser' ),
391
+ 'originalImage' => __( 'Original image', 'shortpixel-image-optimiser' ),
392
+ 'optimizedImage' => __( 'Optimized image', 'shortpixel-image-optimiser' ),
393
+ 'loading' => __( 'Loading...', 'shortpixel-image-optimiser' ),
394
+ // '' => __('', 'shortpixel-image-optimiser' ),
395
+ );
396
+
397
+ /*
398
+ $actions = array(
399
+ 'nonce_check_quota' => wp_create_nonce('check_quota')
400
+ ); */
401
+ wp_localize_script( 'shortpixel', '_spTr', $jsTranslation );
402
+ wp_localize_script( 'shortpixel', 'ShortPixelConstants', $ShortPixelConstants );
403
+ // wp_localize_script('shortpixel', 'ShortPixelActions', $actions);
404
+
405
+ /*
406
+ if (! \wpSPIO()->env()->is_screen_to_use )
407
+ {
408
+ if (! wpSPIO()->env()->is_front) // exeception if this is called to load from your frontie.
409
  return; // not ours, don't load JS and such.
410
+ } */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
411
 
412
+ }
 
 
 
 
 
 
 
 
413
 
414
+ public function admin_styles() {
415
 
416
+ wp_register_style( 'sp-file-tree', plugins_url( '/res/css/sp-file-tree.min.css', SHORTPIXEL_PLUGIN_FILE ), array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION );
417
 
418
+ wp_register_style( 'shortpixel', plugins_url( '/res/css/short-pixel.css', SHORTPIXEL_PLUGIN_FILE ), array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION );
419
 
420
+ // notices. additional styles for SPIO.
421
+ wp_register_style( 'shortpixel-notices', plugins_url( '/res/css/shortpixel-notices.css', SHORTPIXEL_PLUGIN_FILE ), array( 'shortpixel-admin' ), SHORTPIXEL_IMAGE_OPTIMISER_VERSION );
 
 
 
422
 
423
+ // other media screen
424
+ wp_register_style( 'shortpixel-othermedia', plugins_url( '/res/css/shortpixel-othermedia.css', SHORTPIXEL_PLUGIN_FILE ), array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION );
 
 
 
 
 
 
425
 
426
+ // load everywhere, because we are inconsistent.
427
+ wp_register_style( 'shortpixel-toolbar', plugins_url( '/res/css/shortpixel-toolbar.css', SHORTPIXEL_PLUGIN_FILE ), array( 'dashicons' ), SHORTPIXEL_IMAGE_OPTIMISER_VERSION );
 
 
 
428
 
429
+ // @todo Might need to be removed later on
430
+ wp_register_style( 'shortpixel-admin', plugins_url( '/res/css/shortpixel-admin.css', SHORTPIXEL_PLUGIN_FILE ), array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION );
431
 
432
+ wp_register_style( 'shortpixel-bulk', plugins_url( '/res/css/shortpixel-bulk.css', SHORTPIXEL_PLUGIN_FILE ), array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION );
 
 
 
 
 
 
 
 
 
 
433
 
434
+ wp_register_style( 'shortpixel-nextgen', plugins_url( '/res/css/shortpixel-nextgen.css', SHORTPIXEL_PLUGIN_FILE ), array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION );
 
 
 
 
435
 
436
+ wp_register_style( 'shortpixel-settings', plugins_url( '/res/css/shortpixel-settings.css', SHORTPIXEL_PLUGIN_FILE ), array(), SHORTPIXEL_IMAGE_OPTIMISER_VERSION );
 
 
437
 
438
+ }
439
 
 
 
 
 
440
 
441
+ /** Load Style via Route, on demand */
442
+ public function load_style( $name ) {
443
+ if ( $this->is_noheaders ) { // fail silently, if this is a no-headers request.
444
+ return;
445
+ }
446
 
447
+ if ( wp_style_is( $name, 'registered' ) ) {
448
+ wp_enqueue_style( $name );
449
+ } else {
450
+ Log::addWarn( "Style $name was asked for, but not registered" );
451
+ }
452
+ }
453
 
454
+ /** Load Style via Route, on demand */
455
+ public function load_script( $script ) {
456
+ if ( $this->is_noheaders ) { // fail silently, if this is a no-headers request.
457
+ return;
458
+ }
459
 
460
+ if ( ! is_array( $script ) ) {
461
+ $script = array( $script );
462
+ }
 
 
 
 
463
 
464
+ foreach ( $script as $index => $name ) {
465
+ if ( wp_script_is( $name, 'registered' ) ) {
466
+ wp_enqueue_script( $name );
467
+ } else {
468
+ Log::addWarn( "Script $name was asked for, but not registered" );
469
+ }
470
+ }
471
+ }
472
 
473
+ /** This is separated from route to load in head, preventing unstyled content all the time */
474
+ public function load_admin_scripts( $hook_suffix ) {
475
+ global $plugin_page;
476
+ $screen_id = $this->env()->screen_id;
477
 
478
+ //var_dump(\wpSPIO()->env()->is_screen_to_use);
479
+ //exit($screen_id);
480
 
481
+ // $load = array();
482
+ $load_processor = array( 'shortpixel', 'shortpixel-processor' ); // a whole suit needed for processing, not more. Always needs a screen as well!
483
+ $load_bulk = array(); // the whole suit needed for bulking.
 
 
484
 
485
+ if ( $this->env()->is_debug ) {
486
+ $this->load_script( 'shortpixel-debug' );
487
+ }
 
 
 
 
488
 
489
+ if ( \wpSPIO()->env()->is_screen_to_use ) {
490
+ $this->load_script( 'shortpixel-tooltip' );
491
+ $this->load_style( 'shortpixel-toolbar' );
492
 
493
+ }
 
 
 
 
494
 
495
+ if ( $plugin_page == 'wp-shortpixel-settings' ) {
496
+ $this->load_script( $load_processor );
497
+ $this->load_script( 'shortpixel-screen-nolist' ); // screen
498
+ $this->load_script( 'jquery.tooltip.min.js' );
499
+ $this->load_script( 'sp-file-tree' );
500
+ $this->load_script( 'shortpixel-settings' );
501
 
502
+ $this->load_style( 'shortpixel-admin' );
503
+ $this->load_style( 'shortpixel' );
504
+ $this->load_style( 'sp-file-tree' );
505
+ $this->load_style( 'shortpixel-settings' );
506
 
507
+ } elseif ( $plugin_page == 'wp-short-pixel-bulk' ) {
508
+ $this->load_script( $load_processor );
509
+ $this->load_script( 'shortpixel-screen-bulk' );
510
 
511
+ $this->load_style( 'shortpixel-admin' );
512
+ $this->load_style( 'shortpixel-bulk' );
513
+ } elseif ( $screen_id == 'upload' || $screen_id == 'attachment' ) {
514
+ $this->load_script( $load_processor );
515
+ $this->load_script( 'shortpixel-screen-media' ); // screen
 
516
 
517
+ $this->load_style( 'shortpixel-admin' );
518
+ $this->load_style( 'shortpixel' );
519
 
520
+ } elseif ( $plugin_page == 'wp-short-pixel-custom' ) {
521
+ $this->load_style( 'shortpixel' );
522
+ $this->load_style( 'shortpixel-admin' );
523
 
524
+ $this->load_style( 'shortpixel-othermedia' );
525
 
526
+ $this->load_script( $load_processor );
527
+ $this->load_script( 'shortpixel-screen-custom' ); // screen
528
 
529
+ } elseif ( NextGenController::getInstance()->isNextGenScreen() ) {
530
+ $this->load_script( $load_processor );
531
+ $this->load_script( 'shortpixel-screen-custom' ); // screen
532
+ $this->load_style( 'shortpixel-admin' );
 
 
 
 
 
 
 
533
 
534
+ $this->load_style( 'shortpixel' );
535
+ $this->load_style( 'shortpixel-nextgen' );
536
+ }
537
+ elseif ( $this->env()->is_gutenberg_editor === true)
538
+ {
539
+ $this->load_script( $load_processor );
540
+ $this->load_script( 'shortpixel-screen-nolist' ); // screen
541
+ }
542
+ elseif (true === \wpSPIO()->env()->is_screen_to_use )
543
+ {
544
+ // If our screen, but we don't have a specific handler for it, do the no-list screen.
545
+ $this->load_script( $load_processor );
546
+ $this->load_script( 'shortpixel-screen-nolist' ); // screen
547
+ }
548
 
549
+ }
 
550
 
551
+ /** Route, based on the page slug
552
+ *
553
+ * Principially all page controller should be routed from here.
554
+ */
555
+ public function route() {
556
+ global $plugin_page;
557
+ // $this->initPluginRunTime(); // Not in use currently.
558
+ $default_action = 'load'; // generic action on controller.
559
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is not a form
560
+ $action = isset( $_REQUEST['sp-action'] ) ? sanitize_text_field( wp_unslash($_REQUEST['sp-action']) ) : $default_action;
561
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is not a form
562
+ $template_part = isset( $_GET['part'] ) ? sanitize_text_field( wp_unslash($_GET['part']) ) : false;
563
+
564
+ $controller = false;
565
+
566
+ $url = menu_page_url( $plugin_page, false );
567
+ $screen_id = \wpSPIO()->env()->screen_id;
568
+
569
+ switch ( $plugin_page ) {
570
  case 'wp-shortpixel-settings': // settings
571
+ $controller = 'ShortPixel\Controller\SettingsController';
572
+ break;
573
  case 'wp-short-pixel-custom': // other media
574
+
575
+ $controller = 'ShortPixel\Controller\View\OtherMediaViewController';
576
+ break;
577
+ case 'wp-short-pixel-bulk':
578
+ $controller = '\ShortPixel\Controller\View\BulkViewController';
579
+ break;
 
 
 
 
 
 
 
 
 
 
580
  case null:
581
  default:
582
+ switch ( $screen_id ) {
583
+ case 'upload':
 
584
  $controller = '\ShortPixel\Controller\View\ListMediaViewController';
585
+ break;
586
+ case 'attachment'; // edit-media
587
  $controller = '\ShortPixel\Controller\View\EditMediaViewController';
588
  break;
589
 
590
  }
591
+ break;
592
+
593
+ }
594
 
595
+ if ( $controller !== false ) {
596
+ $c = new $controller();
597
+ $c->setControllerURL( $url );
598
+ if ( method_exists( $c, $action ) ) {
599
+ $c->$action();
600
+ } else {
601
+ Log::addWarn( "Attempted Action $action on $controller does not exist!" );
602
+ $c->$default_action();
603
+ }
604
+ }
605
+ }
606
 
 
607
 
608
+ // Get the plugin URL, based on real URL.
609
+ public function plugin_url( $urlpath = '' ) {
610
+ $url = trailingslashit( $this->plugin_url );
611
+ if ( strlen( $urlpath ) > 0 ) {
612
+ $url .= $urlpath;
613
+ }
614
+ return $url;
615
+ }
616
+
617
+ // Get the plugin path.
618
+ public function plugin_path( $path = '' ) {
619
+ $plugin_path = trailingslashit( $this->plugin_path );
620
+ if ( strlen( $path ) > 0 ) {
621
+ $plugin_path .= $path;
622
+ }
623
+
624
+ return $plugin_path;
625
+ }
626
+
627
+ /** Returns defined admin page hooks. Internal use - check states via environmentmodel
628
+ *
629
+ * @returns Array
630
+ */
631
+ public function get_admin_pages() {
632
+ return $this->admin_pages;
633
+ }
634
 
635
+ protected function check_plugin_version() {
636
+ $version = SHORTPIXEL_IMAGE_OPTIMISER_VERSION;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
637
  $db_version = $this->settings()->currentVersion;
638
 
639
+ if ( $version !== $db_version ) {
640
+ InstallHelper::activatePlugin();
641
+ }
 
642
  $this->settings()->currentVersion = $version;
643
  }
644
 
wp-shortpixel.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: ShortPixel Image Optimizer
4
  * Plugin URI: https://shortpixel.com/
5
  * Description: ShortPixel optimizes images automatically, while guarding the quality of your images. Check your <a href="/wp-admin/options-general.php?page=wp-shortpixel-settings" target="_blank">Settings &gt; ShortPixel</a> page on how to start optimizing your image library and make your website load faster.
6
- * Version: 5.0.4
7
  * Author: ShortPixel
8
  * Author URI: https://shortpixel.com
9
  * GitHub Plugin URI: https://github.com/short-pixel-optimizer/shortpixel-image-optimiser
@@ -16,21 +16,22 @@ if (function_exists('wpSPIO'))
16
  {
17
  add_action('admin_notices', function () {
18
  echo '<div class="error"><h4>';
19
- printf(__('ShortPixel plugin already loaded. You might have two versions active. Not loaded: %s', 'shortpixel-image-optimiser'), __FILE__);
20
  echo '</h4></div>';
21
  });
22
  return;
23
  }
24
 
25
  if (! defined('SHORTPIXEL_RESET_ON_ACTIVATE'))
26
- define('SHORTPIXEL_RESET_ON_ACTIVATE', false); //if true TODO set false
 
27
  //define('SHORTPIXEL_DEBUG', true);
28
  //define('SHORTPIXEL_DEBUG_TARGET', true);
29
 
30
  define('SHORTPIXEL_PLUGIN_FILE', __FILE__);
31
  define('SHORTPIXEL_PLUGIN_DIR', __DIR__);
32
 
33
- define('SHORTPIXEL_IMAGE_OPTIMISER_VERSION', "5.0.4");
34
 
35
  define('SHORTPIXEL_BACKUP', 'ShortpixelBackups');
36
  define('SHORTPIXEL_MAX_FAIL_RETRIES', 3);
@@ -68,7 +69,6 @@ define('SHORTPIXEL_BACKUP_URL',
68
  . '/' . SHORTPIXEL_BACKUP);
69
 
70
 
71
- //define("SHORTPIXEL_EXPERIMENTAL_SECURICACHE", true); // tries to add timestamps to URLS, to prevent hitting the cache.
72
  //define('SHORTPIXEL_SILENT_MODE', true); // no global notifications. Can lead to data damage. After setting, reactivate plugin.
73
 
74
  // Starting logging services, early as possible.
3
  * Plugin Name: ShortPixel Image Optimizer
4
  * Plugin URI: https://shortpixel.com/
5
  * Description: ShortPixel optimizes images automatically, while guarding the quality of your images. Check your <a href="/wp-admin/options-general.php?page=wp-shortpixel-settings" target="_blank">Settings &gt; ShortPixel</a> page on how to start optimizing your image library and make your website load faster.
6
+ * Version: 5.0.5
7
  * Author: ShortPixel
8
  * Author URI: https://shortpixel.com
9
  * GitHub Plugin URI: https://github.com/short-pixel-optimizer/shortpixel-image-optimiser
16
  {
17
  add_action('admin_notices', function () {
18
  echo '<div class="error"><h4>';
19
+ printf(esc_html__('ShortPixel plugin already loaded. You might have two versions active. Not loaded: %s', 'shortpixel-image-optimiser'), __FILE__);
20
  echo '</h4></div>';
21
  });
22
  return;
23
  }
24
 
25
  if (! defined('SHORTPIXEL_RESET_ON_ACTIVATE'))
26
+ define('SHORTPIXEL_RESET_ON_ACTIVATE', false);
27
+
28
  //define('SHORTPIXEL_DEBUG', true);
29
  //define('SHORTPIXEL_DEBUG_TARGET', true);
30
 
31
  define('SHORTPIXEL_PLUGIN_FILE', __FILE__);
32
  define('SHORTPIXEL_PLUGIN_DIR', __DIR__);
33
 
34
+ define('SHORTPIXEL_IMAGE_OPTIMISER_VERSION', "5.0.5");
35
 
36
  define('SHORTPIXEL_BACKUP', 'ShortpixelBackups');
37
  define('SHORTPIXEL_MAX_FAIL_RETRIES', 3);
69
  . '/' . SHORTPIXEL_BACKUP);
70
 
71
 
 
72
  //define('SHORTPIXEL_SILENT_MODE', true); // no global notifications. Can lead to data damage. After setting, reactivate plugin.
73
 
74
  // Starting logging services, early as possible.