Robin image optimizer — save money on image compression - Version 1.4.0

Version Description

  • Fixed: Php warning (Declaration of WRIO_Image_Statistic_Folders)
Download this release

Release Info

Developer alexkovalevv
Plugin Icon 128x128 Robin image optimizer — save money on image compression
Version 1.4.0
Comparing to
See all releases

Code changes from version 1.3.7 to 1.4.0

Files changed (168) hide show
  1. admin/activation.php +30 -2
  2. admin/ajax/meta-migrations.php +1 -1
  3. admin/assets/js/bulk-optimization.js +6 -5
  4. admin/boot.php +7 -7
  5. admin/includes/classes/class-rio-optimize-template.php +4 -4
  6. admin/pages/class-rio-license.php +3 -3
  7. admin/pages/class-rio-log.php +4 -2
  8. admin/pages/class-rio-page.php +1 -1
  9. admin/pages/class-rio-settings.php +1 -1
  10. includes/class-rio-plugin.php +3 -3
  11. includes/classes/class-rio-attachment.php +329 -232
  12. includes/classes/class-rio-image-statistic.php +129 -63
  13. includes/classes/class-rio-media-library.php +31 -53
  14. includes/classes/class-rio-views.php +4 -4
  15. includes/classes/logger/class-rio-logger.php +4 -0
  16. includes/classes/models/class-rio-process-queue-table.php +38 -5
  17. includes/functions.php +5 -4
  18. libs/addons/admin/ajax/folders.php +21 -5
  19. libs/addons/admin/assets/js/custom-folders.js +4 -4
  20. libs/addons/admin/boot.php +1 -1
  21. libs/addons/includes/classes/webp/class-webp-listener.php +9 -11
  22. libs/addons/includes/functions.php +110 -0
  23. libs/addons/views/modal-select-custom-folders.php +1 -1
  24. libs/addons/views/part-bulk-optimization-table-folders.php +1 -1
  25. libs/factory/bootstrap/assets/css-min/bootstrap.accordion.min.css +1 -1
  26. libs/factory/bootstrap/assets/css-min/bootstrap.blue.min.css +1 -1
  27. libs/factory/bootstrap/assets/css-min/bootstrap.coffee.min.css +1 -1
  28. libs/factory/bootstrap/assets/css-min/bootstrap.core.min.css +2 -2
  29. libs/factory/bootstrap/assets/css-min/bootstrap.ectoplasm.min.css +1 -1
  30. libs/factory/bootstrap/assets/css-min/bootstrap.form-group.min.css +1 -1
  31. libs/factory/bootstrap/assets/css-min/bootstrap.light.min.css +1 -1
  32. libs/factory/bootstrap/assets/css-min/bootstrap.midnight.min.css +1 -1
  33. libs/factory/bootstrap/assets/css-min/bootstrap.ocean.min.css +1 -1
  34. libs/factory/bootstrap/assets/css-min/bootstrap.separator.min.css +1 -1
  35. libs/factory/bootstrap/assets/css-min/bootstrap.sunrise.min.css +1 -1
  36. libs/factory/bootstrap/assets/css-min/control.checkbox.min.css +1 -1
  37. libs/factory/bootstrap/assets/css-min/control.dropdown.min.css +1 -1
  38. libs/factory/bootstrap/assets/css-min/control.multiple-textbox.min.css +1 -1
  39. libs/factory/bootstrap/assets/css-min/holder.more-link.min.css +1 -1
  40. libs/factory/bootstrap/assets/js-min/bootstrap.dropdown.min.js +1 -1
  41. libs/factory/bootstrap/assets/js-min/control.checkbox.min.js +1 -1
  42. libs/factory/bootstrap/assets/js-min/control.dropdown.min.js +1 -1
  43. libs/factory/bootstrap/assets/js-min/control.list.min.js +1 -1
  44. libs/factory/bootstrap/assets/js-min/control.multiple-textbox.min.js +1 -1
  45. libs/factory/bootstrap/boot.php +6 -6
  46. libs/factory/bootstrap/includes/functions.php +250 -248
  47. libs/factory/clearfy/assets/css/clearfy-base.css +24 -24
  48. libs/factory/clearfy/assets/js/globals.js +15 -15
  49. libs/factory/clearfy/assets/js/license-manager.js +4 -4
  50. libs/factory/clearfy/boot.php +13 -13
  51. libs/factory/clearfy/includes/ajax-handlers.php +8 -8
  52. libs/factory/clearfy/includes/check-clearfy-compatibility.php +11 -11
  53. libs/factory/clearfy/includes/class-clearfy-configurate.php +4 -4
  54. libs/factory/clearfy/includes/class-clearfy-helpers.php +2 -2
  55. libs/factory/clearfy/langs/{wbcr_factory_clearfy_208-ru_RU.mo → wbcr_factory_clearfy_209-ru_RU.mo} +0 -0
  56. libs/factory/clearfy/langs/{wbcr_factory_clearfy_208-ru_RU.po → wbcr_factory_clearfy_209-ru_RU.po} +0 -0
  57. libs/factory/clearfy/pages/class-clearfy-license.php +32 -32
  58. libs/factory/clearfy/pages/class-clearfy-more-features.php +24 -24
  59. libs/factory/clearfy/pages/class-clearfy-pages.php +42 -42
  60. libs/factory/core/boot.php +27 -27
  61. libs/factory/core/includes/activation/class-factory-activator.php +3 -3
  62. libs/factory/core/includes/activation/class-factory-update.php +3 -3
  63. libs/factory/core/includes/assets-managment/class-factory-assets-list.php +4 -4
  64. libs/factory/core/includes/assets-managment/class-factory-script-list.php +2 -2
  65. libs/factory/core/includes/assets-managment/class-factory-style-list.php +1 -1
  66. libs/factory/core/includes/class-check-compatibility.php +3 -3
  67. libs/factory/core/includes/class-factory-migrations.php +187 -140
  68. libs/factory/core/includes/class-factory-notices.php +5 -5
  69. libs/factory/core/includes/class-factory-options.php +1 -1
  70. libs/factory/core/includes/class-factory-plugin-abstract.php +154 -93
  71. libs/factory/core/includes/class-factory-plugin-base.php +16 -19
  72. libs/factory/core/includes/class-factory-requests.php +1 -1
  73. libs/factory/core/includes/class-factory-requirements.php +7 -7
  74. libs/factory/core/includes/entities/class-factory-paths.php +1 -1
  75. libs/factory/core/includes/entities/class-factory-support.php +1 -1
  76. libs/factory/core/includes/functions.php +7 -7
  77. libs/factory/core/includes/premium/class-factory-license-interface.php +1 -1
  78. libs/factory/core/includes/premium/class-factory-manager.php +11 -11
  79. libs/factory/core/includes/premium/class-factory-provider-abstract.php +6 -6
  80. libs/factory/core/includes/updates/class-factory-premium-upgrader.php +15 -15
  81. libs/factory/core/includes/updates/class-factory-upgrader.php +7 -7
  82. libs/factory/core/includes/updates/repositories/class-factory-repository-abstract.php +5 -5
  83. libs/factory/core/includes/updates/repositories/class-factory-wordpress.php +4 -4
  84. libs/factory/core/langs/{wbcr_factory_412-ru_RU.mo → wbcr_factory_414-ru_RU.mo} +0 -0
  85. libs/factory/core/langs/{wbcr_factory_412-ru_RU.po → wbcr_factory_414-ru_RU.po} +0 -0
  86. libs/factory/forms/boot.php +95 -95
  87. libs/factory/forms/controls/checkbox.php +4 -4
  88. libs/factory/forms/controls/color-and-opacity.php +4 -4
  89. libs/factory/forms/controls/color.php +2 -2
  90. libs/factory/forms/controls/customs/html.php +2 -2
  91. libs/factory/forms/controls/customs/separator.php +2 -2
  92. libs/factory/forms/controls/datepicker-range.php +4 -4
  93. libs/factory/forms/controls/dropdown-and-colors.php +6 -6
  94. libs/factory/forms/controls/dropdown.php +5 -5
  95. libs/factory/forms/controls/font.php +11 -11
  96. libs/factory/forms/controls/google-font.php +8 -8
  97. libs/factory/forms/controls/gradient.php +4 -4
  98. libs/factory/forms/controls/hidden.php +2 -2
  99. libs/factory/forms/controls/holders/accordion-item.php +2 -2
  100. libs/factory/forms/controls/holders/accordion.php +2 -2
  101. libs/factory/forms/controls/holders/columns.php +2 -2
  102. libs/factory/forms/controls/holders/control-group-item.php +2 -2
  103. libs/factory/forms/controls/holders/control-group.php +3 -3
  104. libs/factory/forms/controls/holders/div.php +2 -2
  105. libs/factory/forms/controls/holders/form-group.php +2 -2
  106. libs/factory/forms/controls/holders/more-link.php +2 -2
  107. libs/factory/forms/controls/holders/tab-item.php +2 -2
  108. libs/factory/forms/controls/holders/tab.php +4 -4
  109. libs/factory/forms/controls/integer.php +2 -2
  110. libs/factory/forms/controls/list.php +4 -4
  111. libs/factory/forms/controls/multiple-textbox.php +3 -3
  112. libs/factory/forms/controls/paddings-editor.php +3 -3
  113. libs/factory/forms/controls/pattern.php +9 -9
  114. libs/factory/forms/controls/radio-colors.php +2 -2
  115. libs/factory/forms/controls/radio.php +2 -2
  116. libs/factory/forms/controls/textarea.php +2 -2
  117. libs/factory/forms/controls/textbox.php +2 -2
  118. libs/factory/forms/controls/url.php +3 -3
  119. libs/factory/forms/controls/wp-editor.php +3 -3
  120. libs/factory/forms/includes/complex-control.class.php +4 -4
  121. libs/factory/forms/includes/control-holder.class.php +5 -5
  122. libs/factory/forms/includes/control.class.php +5 -5
  123. libs/factory/forms/includes/custom-element.class.php +2 -2
  124. libs/factory/forms/includes/form-element.class.php +7 -7
  125. libs/factory/forms/includes/form-layout.class.php +5 -5
  126. libs/factory/forms/includes/form.class.php +39 -39
  127. libs/factory/forms/includes/holder.class.php +6 -6
  128. libs/factory/forms/includes/html-builder.class.php +2 -2
  129. libs/factory/forms/includes/providers/meta-value-provider.class.php +2 -2
  130. libs/factory/forms/includes/providers/options-value-provider.class.php +3 -3
  131. libs/factory/forms/includes/providers/value-provider.interface.php +2 -2
  132. libs/factory/forms/langs/{wbcr_factory_forms_412-ru_RU.mo → wbcr_factory_forms_414-ru_RU.mo} +0 -0
  133. libs/factory/forms/langs/{wbcr_factory_forms_412-ru_RU.po → wbcr_factory_forms_414-ru_RU.po} +0 -0
  134. libs/factory/forms/layouts/bootstrap-3/bootstrap-3.php +7 -7
  135. libs/factory/freemius/boot.php +13 -13
  136. libs/factory/freemius/includes/class-freemius-api.php +7 -7
  137. libs/factory/freemius/includes/entities/class-freemius-entity.php +1 -1
  138. libs/factory/freemius/includes/entities/class-freemius-license.php +2 -2
  139. libs/factory/freemius/includes/entities/class-freemius-plugin.php +1 -1
  140. libs/factory/freemius/includes/entities/class-freemius-scope.php +1 -1
  141. libs/factory/freemius/includes/entities/class-freemius-site.php +1 -1
  142. libs/factory/freemius/includes/entities/class-freemius-user.php +1 -1
  143. libs/factory/freemius/includes/licensing/class-freemius-provider.php +25 -19
  144. libs/factory/freemius/includes/updates/class-freemius-repository.php +7 -7
  145. libs/factory/pages/boot.php +10 -10
  146. libs/factory/pages/includes/admin-page.class.php +6 -6
  147. libs/factory/pages/includes/page.class.php +6 -6
  148. libs/factory/pages/langs/{wbcr_factory_pages_412-fr_FR.mo → wbcr_factory_pages_414-fr_FR.mo} +0 -0
  149. libs/factory/pages/langs/{wbcr_factory_pages_412-fr_FR.po → wbcr_factory_pages_414-fr_FR.po} +0 -0
  150. libs/factory/pages/langs/{wbcr_factory_pages_412-ru_RU.mo → wbcr_factory_pages_414-ru_RU.mo} +0 -0
  151. libs/factory/pages/langs/{wbcr_factory_pages_412-ru_RU.po → wbcr_factory_pages_414-ru_RU.po} +0 -0
  152. libs/factory/pages/pages.php +11 -11
  153. libs/factory/pages/templates/assets/css/impressive.page.template.css +116 -116
  154. libs/factory/pages/templates/impressive-page.class.php +31 -31
  155. migrations/010009.php +30 -2
  156. migrations/010300.php +22 -14
  157. migrations/010306.php +31 -8
  158. migrations/010309.php +87 -0
  159. readme.txt +17 -1
  160. robin-image-optimizer.php +8 -8
  161. views/clearfy-component-card.php +1 -1
  162. views/part-bulk-optimization-button.php +1 -1
  163. views/part-bulk-optimization-log.php +2 -2
  164. views/part-bulk-optimization-select-site.php +1 -1
  165. views/part-bulk-optimization-servers.php +1 -1
  166. views/part-bulk-optimization-statistic.php +1 -1
  167. views/part-bulk-optimization-tabs.php +1 -1
  168. views/part-page-header.php +1 -1
admin/activation.php CHANGED
@@ -5,7 +5,7 @@
5
  *
6
  * @author Webcraftic <wordpress.webraftic@gmail.com>
7
  * @copyright (c) 09.09.2017, Webcraftic
8
- * @see Factory412_Activator
9
  * @version 1.0
10
  */
11
 
@@ -14,7 +14,7 @@ if ( ! defined( 'ABSPATH' ) ) {
14
  exit;
15
  }
16
 
17
- class WIO_Activation extends Wbcr_Factory412_Activator {
18
 
19
  /**
20
  * Runs activation actions.
@@ -36,11 +36,39 @@ class WIO_Activation extends Wbcr_Factory412_Activator {
36
  WRIO_Logger::info( 'Premium plugin installation complete!' );
37
  }
38
 
 
 
 
 
 
 
 
 
 
 
 
39
  RIO_Process_Queue::try_create_plugin_tables();
40
 
 
 
41
  WRIO_Logger::info( 'Parent plugin installation complete!' );
42
  }
43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  /**
45
  * Runs activation actions.
46
  *
5
  *
6
  * @author Webcraftic <wordpress.webraftic@gmail.com>
7
  * @copyright (c) 09.09.2017, Webcraftic
8
+ * @see Factory414_Activator
9
  * @version 1.0
10
  */
11
 
14
  exit;
15
  }
16
 
17
+ class WIO_Activation extends Wbcr_Factory414_Activator {
18
 
19
  /**
20
  * Runs activation actions.
36
  WRIO_Logger::info( 'Premium plugin installation complete!' );
37
  }
38
 
39
+ $db_version = RIO_Process_Queue::get_db_version();
40
+ $plugin_version_in_db = $this->get_plugin_version_in_db();
41
+ $current_plugin_version = $this->plugin->getPluginVersion();
42
+
43
+ $create_table_log_message = "Plugin installation: try create plugin tables.\r\n";
44
+ $create_table_log_message .= "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t-DB Version: {$db_version}\r\n";
45
+ $create_table_log_message .= "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t-Plugin Version in DB: {$plugin_version_in_db}\r\n";
46
+ $create_table_log_message .= "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t-Current Plugin Version: {$current_plugin_version}";
47
+
48
+ WRIO_Logger::info( $create_table_log_message );
49
+
50
  RIO_Process_Queue::try_create_plugin_tables();
51
 
52
+ WbcrFactoryClearfy209_Helpers::flushPageCache();
53
+
54
  WRIO_Logger::info( 'Parent plugin installation complete!' );
55
  }
56
 
57
+ /**
58
+ * Get previous plugin version
59
+ *
60
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
61
+ * @since 1.3.8
62
+ * @return number
63
+ */
64
+ public function get_plugin_version_in_db() {
65
+ if ( WRIO_Plugin::app()->isNetworkActive() ) {
66
+ return get_site_option( WRIO_Plugin::app()->getOptionName( 'plugin_version' ), 0 );
67
+ }
68
+
69
+ return get_option( WRIO_Plugin::app()->getOptionName( 'plugin_version' ), 0 );
70
+ }
71
+
72
  /**
73
  * Runs activation actions.
74
  *
admin/ajax/meta-migrations.php CHANGED
@@ -157,7 +157,7 @@ function wbcr_rio_migrate_postmeta_to_process_queue() {
157
  WRIO_Logger::info( 'Succefull migrated all items. Finishing-up...' );
158
 
159
  // Assumed to be 2 after 010105.php migration
160
- WRIO_Plugin::app()->updateOption( 'db_version', 2 );
161
 
162
  $need_more_time = false;
163
  $message = __( 'Finishing-up...', 'robin-image-optimizer' );
157
  WRIO_Logger::info( 'Succefull migrated all items. Finishing-up...' );
158
 
159
  // Assumed to be 2 after 010105.php migration
160
+ RIO_Process_Queue::update_db_version(2);
161
 
162
  $need_more_time = false;
163
  $message = __( 'Finishing-up...', 'robin-image-optimizer' );
admin/assets/js/bulk-optimization.js CHANGED
@@ -289,10 +289,10 @@ jQuery(function($) {
289
  throwError: function(error_message) {
290
  this.stop();
291
 
292
- var noticeId = $.wbcr_factory_clearfy_208.app.showNotice(error_message, 'danger');
293
 
294
  setTimeout(function() {
295
- $.wbcr_factory_clearfy_208.app.hideNotice(noticeId);
296
  }, 10000);
297
  },
298
 
@@ -386,8 +386,8 @@ jQuery(function($) {
386
  trEl.addClass('wrio-error');
387
  }
388
 
389
- var preview = $('<img width="40" height="40" src="' + value.url + '" alt="">'),
390
- previewUrl = $('<a href="' + value.url + '">' + value.file_name + '</a>');
391
 
392
  tableEl.prepend(trEl);
393
 
@@ -395,7 +395,8 @@ jQuery(function($) {
395
  trEl.append(tdEl.clone().append(previewUrl));
396
 
397
  if( 'error' === value.type ) {
398
- trEl.append(tdEl.clone().attr('colspan', '5').text("Error: " + value.error_msg));
 
399
  } else {
400
  trEl.append(tdEl.clone().text(value.original_size));
401
  trEl.append(tdEl.clone().text(value.optimized_size));
289
  throwError: function(error_message) {
290
  this.stop();
291
 
292
+ var noticeId = $.wbcr_factory_clearfy_209.app.showNotice(error_message, 'danger');
293
 
294
  setTimeout(function() {
295
+ $.wbcr_factory_clearfy_209.app.hideNotice(noticeId);
296
  }, 10000);
297
  },
298
 
386
  trEl.addClass('wrio-error');
387
  }
388
 
389
+ var preview = $('<img width="40" height="40" src="' + value.thumbnail_url + '" alt="">'),
390
+ previewUrl = $('<a href="' + value.url + '" target="_blank">' + value.file_name + '</a>');
391
 
392
  tableEl.prepend(trEl);
393
 
395
  trEl.append(tdEl.clone().append(previewUrl));
396
 
397
  if( 'error' === value.type ) {
398
+ var colspan = value.scope !== 'custom-folders' ? '6' : '5';
399
+ trEl.append(tdEl.clone().attr('colspan', colspan).text("Error: " + value.error_msg));
400
  } else {
401
  trEl.append(tdEl.clone().text(value.original_size));
402
  trEl.append(tdEl.clone().text(value.optimized_size));
admin/boot.php CHANGED
@@ -73,7 +73,7 @@ add_action( 'admin_enqueue_scripts', function () {
73
 
74
  wp_enqueue_script( 'wrio-meta-migrations', WRIO_PLUGIN_URL . '/admin/assets/js/meta-migrations.js', [
75
  'jquery',
76
- 'wbcr-factory-clearfy-208-global'
77
  ], WRIO_Plugin::app()->getPluginVersion() );
78
  } );
79
 
@@ -126,8 +126,8 @@ add_action( "wbcr_factory_notices_000_list", function ( $notices ) {
126
  * @author Alexander Kovalev <alex.kovalevv@gmail.com>
127
  * @since 1.3.0
128
  *
129
- * @param Wbcr_Factory412_Plugin $plugin
130
- * @param Wbcr_FactoryPages412_ImpressiveThemplate $obj
131
  *
132
  * @see wbcr_rio_migrate_postmeta_to_process_queue() for further information about AJAX processing function.
133
  * @see wbcr_rio_has_meta_to_migrate() used to check whether to show notice or not.
@@ -146,11 +146,11 @@ add_action( 'wbcr/factory/pages/impressive/print_all_notices', function ( $plugi
146
  * Flush configuration after saving the settings
147
  *
148
  * @param WHM_Plugin $plugin
149
- * @param Wbcr_FactoryPages412_ImpressiveThemplate $obj
150
  *
151
  * @return bool
152
  */
153
- /*add_action('wbcr_factory_412_imppage_after_form_save', function ($plugin, $obj) {
154
  $is_rio = WRIO_Plugin::app()->getPluginName() == $plugin->getPluginName();
155
 
156
  if( $is_rio ) {
@@ -174,14 +174,14 @@ function wio_rating_widget_url( $page_url, $plugin_name ) {
174
  return $page_url;
175
  }
176
 
177
- add_filter( 'wbcr_factory_pages_412_imppage_rating_widget_url', 'wio_rating_widget_url', 10, 2 );
178
 
179
  /**
180
  * Widget with the offer to buy Clearfy Business
181
  *
182
  * @param array $widgets
183
  * @param string $position
184
- * @param Wbcr_Factory412_Plugin $plugin
185
  */
186
  add_filter( 'wbcr/factory/pages/impressive/widgets', function ( $widgets, $position, $plugin ) {
187
  if ( $plugin->getPluginName() == WRIO_Plugin::app()->getPluginName() ) {
73
 
74
  wp_enqueue_script( 'wrio-meta-migrations', WRIO_PLUGIN_URL . '/admin/assets/js/meta-migrations.js', [
75
  'jquery',
76
+ 'wbcr-factory-clearfy-209-global'
77
  ], WRIO_Plugin::app()->getPluginVersion() );
78
  } );
79
 
126
  * @author Alexander Kovalev <alex.kovalevv@gmail.com>
127
  * @since 1.3.0
128
  *
129
+ * @param Wbcr_Factory414_Plugin $plugin
130
+ * @param Wbcr_FactoryPages414_ImpressiveThemplate $obj
131
  *
132
  * @see wbcr_rio_migrate_postmeta_to_process_queue() for further information about AJAX processing function.
133
  * @see wbcr_rio_has_meta_to_migrate() used to check whether to show notice or not.
146
  * Flush configuration after saving the settings
147
  *
148
  * @param WHM_Plugin $plugin
149
+ * @param Wbcr_FactoryPages414_ImpressiveThemplate $obj
150
  *
151
  * @return bool
152
  */
153
+ /*add_action('wbcr_factory_414_imppage_after_form_save', function ($plugin, $obj) {
154
  $is_rio = WRIO_Plugin::app()->getPluginName() == $plugin->getPluginName();
155
 
156
  if( $is_rio ) {
174
  return $page_url;
175
  }
176
 
177
+ add_filter( 'wbcr_factory_pages_414_imppage_rating_widget_url', 'wio_rating_widget_url', 10, 2 );
178
 
179
  /**
180
  * Widget with the offer to buy Clearfy Business
181
  *
182
  * @param array $widgets
183
  * @param string $position
184
+ * @param Wbcr_Factory414_Plugin $plugin
185
  */
186
  add_filter( 'wbcr/factory/pages/impressive/widgets', function ( $widgets, $position, $plugin ) {
187
  if ( $plugin->getPluginName() == WRIO_Plugin::app()->getPluginName() ) {
admin/includes/classes/class-rio-optimize-template.php CHANGED
@@ -26,12 +26,12 @@ class WIO_OptimizePageTemplate {
26
  /**
27
  * Выводит контент страницы с учётом мультисайта
28
  *
29
- * @param Wbcr_FactoryClearfy208_PageBase $page
30
  *
31
  * @throws Exception
32
  */
33
 
34
- /*public function showPageContent( Wbcr_FactoryClearfy208_PageBase $page ) {
35
  do_action( 'wbcr/rio/multisite_current_blog' );
36
  $this->pageContent( $page );
37
  do_action( 'wbcr/rio/multisite_restore_blog' );
@@ -174,7 +174,7 @@ class WIO_OptimizePageTemplate {
174
  class="wio-reoptimize button-wio-manual-override-upload"
175
  data-waiting-label="<?php _e( 'Optimization in progress', 'robin-image-optimizer' ); ?>">
176
  <span class="dashicons dashicons-admin-generic"></span><span
177
- class="wio-hide-if-small"><?php _e( 'Re-Optimize to', 'robin-image-optimizer' ); ?> </span><?php _e( 'Normal', 'robin-image-optimizer' ); ?>
178
  <span class="wio-hide-if-small"></span>
179
  </a>
180
  <?php endif; ?>
@@ -184,7 +184,7 @@ class WIO_OptimizePageTemplate {
184
  class="wio-reoptimize button-wio-manual-override-upload"
185
  data-waiting-label="<?php _e( 'Optimization in progress', 'robin-image-optimizer' ); ?>">
186
  <span class="dashicons dashicons-admin-generic"></span><span
187
- class="wio-hide-if-small"><?php _e( 'Re-Optimize to', 'robin-image-optimizer' ); ?> </span><?php _e( 'Medium', 'robin-image-optimizer' ); ?>
188
  <span class="wio-hide-if-small"></span>
189
  </a>
190
  <?php endif; ?>
26
  /**
27
  * Выводит контент страницы с учётом мультисайта
28
  *
29
+ * @param Wbcr_FactoryClearfy209_PageBase $page
30
  *
31
  * @throws Exception
32
  */
33
 
34
+ /*public function showPageContent( Wbcr_FactoryClearfy209_PageBase $page ) {
35
  do_action( 'wbcr/rio/multisite_current_blog' );
36
  $this->pageContent( $page );
37
  do_action( 'wbcr/rio/multisite_restore_blog' );
174
  class="wio-reoptimize button-wio-manual-override-upload"
175
  data-waiting-label="<?php _e( 'Optimization in progress', 'robin-image-optimizer' ); ?>">
176
  <span class="dashicons dashicons-admin-generic"></span><span
177
+ class="wio-hide-if-small"><?php _e( 'Re-Optimize to', 'robin-image-optimizer' ); ?> </span><?php _e( 'lossless', 'robin-image-optimizer' ); ?>
178
  <span class="wio-hide-if-small"></span>
179
  </a>
180
  <?php endif; ?>
184
  class="wio-reoptimize button-wio-manual-override-upload"
185
  data-waiting-label="<?php _e( 'Optimization in progress', 'robin-image-optimizer' ); ?>">
186
  <span class="dashicons dashicons-admin-generic"></span><span
187
+ class="wio-hide-if-small"><?php _e( 'Re-Optimize to', 'robin-image-optimizer' ); ?> </span><?php _e( 'lossy', 'robin-image-optimizer' ); ?>
188
  <span class="wio-hide-if-small"></span>
189
  </a>
190
  <?php endif; ?>
admin/pages/class-rio-license.php CHANGED
@@ -9,7 +9,7 @@ if ( ! defined( 'ABSPATH' ) ) {
9
  *
10
  * @author Alexander Teshabaev <sasha.tesh@gmail.com>
11
  */
12
- class WRIO_License_Page extends Wbcr_FactoryClearfy208_LicensePage {
13
 
14
  /**
15
  * {@inheritdoc}
@@ -43,9 +43,9 @@ class WRIO_License_Page extends Wbcr_FactoryClearfy208_LicensePage {
43
 
44
  /**
45
  * {@inheritdoc}
46
- * @param Wbcr_Factory412_Plugin $plugin
47
  */
48
- public function __construct( Wbcr_Factory412_Plugin $plugin ) {
49
  $this->menu_title = __( 'License', 'robin-image-optimizer' );
50
  $this->page_menu_short_description = __( 'Product activation', 'robin-image-optimizer' );
51
 
9
  *
10
  * @author Alexander Teshabaev <sasha.tesh@gmail.com>
11
  */
12
+ class WRIO_License_Page extends Wbcr_FactoryClearfy209_LicensePage {
13
 
14
  /**
15
  * {@inheritdoc}
43
 
44
  /**
45
  * {@inheritdoc}
46
+ * @param Wbcr_Factory414_Plugin $plugin
47
  */
48
+ public function __construct( Wbcr_Factory414_Plugin $plugin ) {
49
  $this->menu_title = __( 'License', 'robin-image-optimizer' );
50
  $this->page_menu_short_description = __( 'Product activation', 'robin-image-optimizer' );
51
 
admin/pages/class-rio-log.php CHANGED
@@ -49,6 +49,8 @@ class WRIO_LogPage extends WRIO_Page {
49
  public function assets( $scripts, $styles ) {
50
  parent::assets( $scripts, $styles );
51
 
 
 
52
  // Add Clearfy styles for HMWP pages
53
  if ( defined( 'WBCR_CLEARFY_PLUGIN_ACTIVE' ) ) {
54
  $this->styles->add( WCL_PLUGIN_URL . '/admin/assets/css/general.css' );
@@ -104,10 +106,10 @@ class WRIO_LogPage extends WRIO_Page {
104
 
105
  jQuery('#wbcr-log-viewer').html('');
106
  jQuery('#wbcr-log-size').text('0B');
107
- jQuery.wbcr_factory_clearfy_208.app.showNotice(data.message, data.type);
108
  },
109
  error: function(jqXHR, textStatus, errorThrown) {
110
- jQuery.wbcr_factory_clearfy_208.app.showNotice('Error: ' + errorThrown + ', status: ' + textStatus, 'danger');
111
  btn.html(currentBtnText);
112
  }
113
  });
49
  public function assets( $scripts, $styles ) {
50
  parent::assets( $scripts, $styles );
51
 
52
+ $this->styles->add( WRIO_PLUGIN_URL . '/admin/assets/css/base-statistic.css' );
53
+
54
  // Add Clearfy styles for HMWP pages
55
  if ( defined( 'WBCR_CLEARFY_PLUGIN_ACTIVE' ) ) {
56
  $this->styles->add( WCL_PLUGIN_URL . '/admin/assets/css/general.css' );
106
 
107
  jQuery('#wbcr-log-viewer').html('');
108
  jQuery('#wbcr-log-size').text('0B');
109
+ jQuery.wbcr_factory_clearfy_209.app.showNotice(data.message, data.type);
110
  },
111
  error: function(jqXHR, textStatus, errorThrown) {
112
+ jQuery.wbcr_factory_clearfy_209.app.showNotice('Error: ' + errorThrown + ', status: ' + textStatus, 'danger');
113
  btn.html(currentBtnText);
114
  }
115
  });
admin/pages/class-rio-page.php CHANGED
@@ -18,7 +18,7 @@ if ( ! defined( 'ABSPATH' ) ) {
18
  * @copyright (c) 2018, Webcraftic
19
  * @version 1.0
20
  */
21
- class WRIO_Page extends Wbcr_FactoryClearfy208_PageBase {
22
 
23
  /**
24
  * {@inheritdoc}
18
  * @copyright (c) 2018, Webcraftic
19
  * @version 1.0
20
  */
21
+ class WRIO_Page extends Wbcr_FactoryClearfy209_PageBase {
22
 
23
  /**
24
  * {@inheritdoc}
admin/pages/class-rio-settings.php CHANGED
@@ -44,7 +44,7 @@ class WRIO_SettingsPage extends WRIO_Page {
44
  *
45
  * @since 1.0.0
46
  * @return void
47
- * @see Wbcr_FactoryPages412_AdminPage
48
  *
49
  */
50
  public function assets( $scripts, $styles ) {
44
  *
45
  * @since 1.0.0
46
  * @return void
47
+ * @see Wbcr_FactoryPages414_AdminPage
48
  *
49
  */
50
  public function assets( $scripts, $styles ) {
includes/class-rio-plugin.php CHANGED
@@ -11,10 +11,10 @@ if ( ! defined( 'ABSPATH' ) ) {
11
  * @copyright (c) 19.02.2018, Webcraftic
12
  * @version 1.0
13
  */
14
- class WRIO_Plugin extends Wbcr_Factory412_Plugin {
15
 
16
  /**
17
- * @var Wbcr_Factory412_Plugin
18
  */
19
  private static $app;
20
 
@@ -89,7 +89,7 @@ class WRIO_Plugin extends Wbcr_Factory412_Plugin {
89
  /**
90
  * Статический метод для быстрого доступа к информации о плагине, а также часто использумых методах.
91
  *
92
- * @return Wbcr_Factory412_Plugin
93
  */
94
  public static function app() {
95
  return self::$app;
11
  * @copyright (c) 19.02.2018, Webcraftic
12
  * @version 1.0
13
  */
14
+ class WRIO_Plugin extends Wbcr_Factory414_Plugin {
15
 
16
  /**
17
+ * @var Wbcr_Factory414_Plugin
18
  */
19
  private static $app;
20
 
89
  /**
90
  * Статический метод для быстрого доступа к информации о плагине, а также часто использумых методах.
91
  *
92
+ * @return Wbcr_Factory414_Plugin
93
  */
94
  public static function app() {
95
  return self::$app;
includes/classes/class-rio-attachment.php CHANGED
@@ -8,104 +8,186 @@ if ( ! defined( 'ABSPATH' ) ) {
8
  /**
9
  * Класс для работы с WordPress attachment.
10
  *
11
- * @author Eugene Jokerov <jokerov@gmail.com>
12
  * @copyright (c) 2018, Webcraftic
13
- * @version 1.0
14
  */
15
  class WIO_Attachment {
16
-
17
  /**
18
  * @var int
19
  */
20
  private $id;
21
-
 
22
  /**
23
  * @var array meta-данные
24
  */
25
  private $attachment_meta;
26
-
27
  /**
28
  * @var array массив с данными о папке uploads
29
  */
30
  private $wp_upload_dir;
31
-
32
  /**
33
  * @var string
34
  */
35
  private $url;
36
-
37
  /**
38
  * @var string
39
  */
40
  private $path;
41
-
42
  /**
43
  * @var RIO_Process_Queue
44
  */
45
  private $optimization_data;
46
-
47
  /**
48
  * Инициализация аттачмента
49
  *
50
- * @param int $attachment_id Номер аттачмента из медиабиблиотеки
51
- * @param array|false $attachment_meta метаданные аттачмента. Ключи массива аналогичны функции wp_get_attachment_metadata
52
  */
53
  public function __construct( $attachment_id, $attachment_meta = false ) {
54
  $this->id = $attachment_id;
55
  $this->wp_upload_dir = wp_upload_dir();
56
  $this->attachment_meta = $attachment_meta;
57
-
58
  if ( ! $attachment_meta ) {
59
  // some meta can be missing due to: https://wordpress.stackexchange.com/q/330174/149161
60
  $this->attachment_meta = wp_get_attachment_metadata( $this->id );
61
  }
62
-
63
- if ( $this->attachment_meta && isset( $this->attachment_meta['file'] ) ) {
64
- $this->url = trailingslashit( $this->wp_upload_dir['baseurl'] ) . $this->attachment_meta['file'];
65
- $this->path = wp_normalize_path( trailingslashit( $this->wp_upload_dir['basedir'] ) . $this->attachment_meta['file'] );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  }
 
 
 
67
  }
68
-
69
  /**
70
  * Актуализирует мета данные аттачмента и загружает актуальные мета данные и данные по оптимизации из базы.
71
  */
72
- public function reload() {
73
- $this->attachment_meta = wp_get_attachment_metadata( $this->id );
74
- $this->optimization_data = new RIO_Process_Queue( array(
 
 
 
75
  'object_id' => $this->id,
76
  'object_name' => '',
77
  'item_type' => 'attachment',
78
- ) );
79
  $this->optimization_data->load();
 
80
  }
81
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  /**
83
  * Добавляем сообщение в лог файл.
84
  *
85
- * @param string $message Текст сообщения об ошибке.
86
  */
87
  public function writeLog( $message ) {
88
-
89
  $char = "\t-> ";
90
  $nl = PHP_EOL;
91
-
92
  $error = sprintf( 'Error to optimize attachment (ID: #%s). Message: "%s"', $this->id, trim( $message ) ) . $nl;
93
  $error .= $char . sprintf( "Attachment optimized? %s", ( $this->isOptimized() ? 'Yes' : 'No' ) ) . $nl;
94
  $error .= $char . sprintf( "Should be resized? %s", ( $this->isNeedResize() ? 'Yes' : 'No' ) ) . $nl;
95
  $error .= $char . sprintf( "Original size: %sx%s", $this->attachment_meta['width'], $this->attachment_meta['height'] ) . $nl;
96
  $error .= $char . sprintf( "Relative path: %s", $this->attachment_meta['file'] ) . $nl;
97
  $error .= $char . sprintf( "Server used: %s", WRIO_Plugin::app()->getPopulateOption( 'image_optimization_server', 'server_1' ) ) . $nl;
98
-
99
  if ( ! empty( $this->attachment_meta['sizes'] ) ) {
100
  $error .= $char . ' Additional sizes:' . $nl;
101
  foreach ( $this->attachment_meta['sizes'] as $size_type => $size_info ) {
102
  $error .= "\t" . $char . sprintf( 'Type: %s, size: %sx%s, MIME type: %s', $size_type, $size_info['width'], $size_info['height'], $size_info['mime-type'] ) . $nl;
103
  }
104
  }
105
-
106
  WRIO_Logger::error( $error );
107
  }
108
-
109
  /**
110
  * Возвращает объект с информацией об оптимизации
111
  *
@@ -113,243 +195,258 @@ class WIO_Attachment {
113
  */
114
  public function getOptimizationData() {
115
  if ( ! isset( $optimization_data ) ) {
116
- $this->optimization_data = new RIO_Process_Queue( array(
117
  'object_id' => $this->id,
118
  'object_name' => '',
119
  'item_type' => 'attachment',
120
- ) );
121
  $this->optimization_data->load();
122
  }
123
-
124
  return $this->optimization_data;
125
  }
126
-
127
  /**
128
  * Оптимизация аттачмента.
129
  *
130
- * @param string $optimization_level Уровень оптимизации изображения.
131
  *
132
  * @return array
133
  */
134
  public function optimize( $optimization_level = '' ) {
135
- $optimize_results = array(
136
  'original_size' => 0,
137
  'optimized_size' => 0,
138
- );
139
-
140
  if ( empty( $optimization_level ) ) {
141
  $optimization_level = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_level', 'normal' );
142
  }
143
-
144
  if ( $optimization_level == 'custom' ) {
145
  $custom_quality = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_level_custom', 100 );
146
  $optimization_level = intval( $custom_quality );
147
  }
148
-
149
  $optimization_data = $this->getOptimizationData();
150
- $results = array(
151
  'original_size' => 0,
152
  'final_size' => 0,
153
  'original_mime_type' => '',
154
  'final_mime_type' => '',
155
- );
156
  $results['processing_level'] = $optimization_level;
157
-
158
- $path = $this->get( 'path' );
159
-
160
- // проверяем наличие основного файла, если его нет, то исключаем из дальнейшей обработки
161
- if ( ! file_exists( $path ) ) {
 
 
 
 
 
162
  $results['result_status'] = 'error';
163
- $extra_data = array(
 
 
 
 
 
 
 
 
 
164
  'error' => 'path',
165
- 'error_msg' => sprintf( 'File path %s', ( empty( $path ) ) ? 'is empty' : $path . ' does not exist' ),
166
- );
167
- $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
 
168
  $optimization_data->configure( $results );
169
  $optimization_data->save();
170
-
171
  WRIO_Logger::error( sprintf( 'Failed to find original attachment #%s located in %s. Skipping optimization. This may be caused due to bug in %s function, which returns false for attachment meta', $this->id, empty( $path ) ? '*empty path*' : $path, 'wp_get_attachment_metadata()' ) );
172
-
173
  return $optimize_results;
174
  }
175
-
176
  // сначала бекапим
177
  $is_image_backuped = $this->backup();
178
-
179
  if ( is_wp_error( $is_image_backuped ) ) {
180
  $error_msg = $is_image_backuped->get_error_message();
181
  $this->writeLog( $error_msg );
182
-
183
  $results['result_status'] = 'error';
184
- $extra_data = array(
185
  'error' => 'backup',
186
  'error_msg' => 'Failed to backup',
187
- );
188
  $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
189
  $optimization_data->configure( $results );
190
  $optimization_data->save();
191
-
192
  WRIO_Logger::error( sprintf( 'Failed to make backup of original attachment #%s. Skipping optimization.', $this->id ) );
193
-
194
  return $optimize_results;
195
  }
196
-
197
  $results['is_backed_up'] = $is_image_backuped;
198
-
199
- $original_main_size = filesize( $path );
200
-
201
  // если файл большой - изменяем размер
202
  if ( $this->isNeedResize() ) {
203
  $this->resize();
204
  }
205
-
206
  $image_processor = WIO_OptimizationTools::getImageProcessor();
207
-
208
  clearstatcache(); // на всякий случай очистим кеш файловой статистики
209
-
210
- $optimized_img_data = $image_processor->process( array(
211
  'image_url' => $this->get( 'url' ),
212
  'image_path' => $this->get( 'path' ),
213
  'quality' => $image_processor->quality( $optimization_level ),
214
  'save_exif' => WRIO_Plugin::app()->getPopulateOption( 'save_exif_data', false ),
215
- ) );
216
-
217
  // проверяем на ошибку
218
  if ( is_wp_error( $optimized_img_data ) ) {
219
  $error_msg = $optimized_img_data->get_error_message();
220
  $this->writeLog( $error_msg );
221
-
222
  $results['result_status'] = 'error';
223
-
224
- $extra_data = array(
225
  'error' => 'optimization',
226
  'error_msg' => $error_msg,
227
- );
228
-
229
  $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
230
-
231
  $optimization_data->configure( $results );
232
  $optimization_data->save();
233
-
234
  WRIO_Logger::error( sprintf( 'Failed to process (url: %s, path: %s, quality: %s) as error was returned: %s', $this->get( 'url' ), $this->get( 'path' ), $image_processor->quality( $optimization_level ), $error_msg ) );
235
-
236
  return $optimize_results;
237
  }
238
-
239
  $results['original_mime_type'] = '';
240
  $results['final_mime_type'] = '';
241
-
242
  // отложенная оптимизация
243
  if ( isset( $optimized_img_data['status'] ) && $optimized_img_data['status'] == 'processing' ) {
244
  $results['result_status'] = 'processing';
245
  $results['original_size'] = 0;
246
  $results['final_size'] = 0;
247
-
248
- $extra_data = array(
249
  'main_optimized_data' => $optimized_img_data,
250
  'thumbnails_optimized_data' => $this->optimizeImageSizes(),
251
- );
252
-
253
  $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
254
-
255
  $optimization_data->configure( $results );
256
  $optimization_data->save();
257
  $optimize_results['processing'] = 1;
258
-
259
  return $optimize_results;
260
  }
261
-
262
  //скачиваем и заменяем главную картинку
263
  $image_downloaded = $this->replaceOriginalFile( $optimized_img_data );
264
-
265
  // некоторые провайдеры не отдают оптимизированный размер, поэтому после замены файла получаем его сами
266
  if ( ! $optimized_img_data['optimized_size'] ) {
267
  clearstatcache();
268
  $optimized_img_data['optimized_size'] = filesize( $this->get( 'path' ) );
269
  }
270
-
271
  // при отрицательной оптимизации ставим значение оригинала
272
  if ( $optimized_img_data['optimized_size'] > $original_main_size ) {
273
  $optimized_img_data['optimized_size'] = $original_main_size;
274
  }
275
-
276
  if ( $image_downloaded ) {
277
  //просчитываем статистику
278
  $optimize_results['original_size'] += $original_main_size;
279
  $optimize_results['optimized_size'] += $optimized_img_data['optimized_size'];
280
  $thumbnails_count = 0;
281
-
282
  // оптимизируем дополнительные размеры
283
  $optimized_img_sizes_data = $this->optimizeImageSizes();
284
-
285
  // добавляем к статистике данные по оптимизации доп размеров
286
  if ( ! empty( $optimized_img_sizes_data ) ) {
287
  $optimize_results['original_size'] += $optimized_img_sizes_data['original_size'];
288
  $optimize_results['optimized_size'] += $optimized_img_sizes_data['optimized_size'];
289
  $thumbnails_count = $optimized_img_sizes_data['thumbnails_count'];
290
  }
291
-
292
  $results['result_status'] = 'success';
293
  $results['final_size'] = $optimize_results['optimized_size'];
294
  $results['original_size'] = $optimize_results['original_size'];
295
-
296
- $extra_data = array(
297
  'thumbnails_count' => $thumbnails_count,
298
  'original_main_size' => $original_main_size,
299
- );
300
-
301
  $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
302
  $mime_type = '';
303
-
304
  if ( function_exists( 'wp_get_image_mime' ) ) {
305
  $mime_type = wp_get_image_mime( $this->get( 'path' ) );
306
  } else {
307
  WRIO_Logger::error( 'App is missing wp_get_image_mime() function, unable to get MIME type' );
308
  }
309
-
310
  $results['original_mime_type'] = $mime_type;
311
  $results['final_mime_type'] = $mime_type;
312
  $optimization_data->configure( $results );
313
  } else {
314
  $error_msg = 'Failed to get optimized image from remote server';
315
  $this->writeLog( $error_msg );
316
-
317
  $results['result_status'] = 'error';
318
-
319
- $extra_data = array(
320
  'error' => 'download',
321
  'error_msg' => $error_msg,
322
- );
323
-
324
  $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
325
  $optimization_data->configure( $results );
326
  }
327
-
328
  $optimization_data->save();
329
-
330
  return $optimize_results;
331
  }
332
-
333
  /**
334
  * Отложенная оптимизация аттачмента
335
  *
336
  * @return bool|array
337
  */
338
  public function deferredOptimization() {
339
- $results = array(
340
  'original_size' => 0,
341
  'optimized_size' => 0,
342
  'optimized_count' => 0,
343
  'processing' => 1,
344
- );
345
-
346
  $image_processor = WIO_OptimizationTools::getImageProcessor();
347
  $optimization_data = $this->getOptimizationData();
348
-
349
  if ( $optimization_data->get_result_status() != 'processing' ) {
350
  return false;
351
  }
352
-
353
  // проверяем главную картинку
354
  /**
355
  * @var RIO_Attachment_Extra_Data $extra_data
@@ -357,7 +454,7 @@ class WIO_Attachment {
357
  $extra_data = $optimization_data->get_extra_data();
358
  $main_optimized_data = $extra_data->get_main_optimized_data();
359
  $main_image_url = '';
360
-
361
  if ( ! $main_optimized_data['optimized_img_url'] ) {
362
  $main_image_url = $image_processor->checkDeferredOptimization( $main_optimized_data );
363
  if ( $main_image_url ) {
@@ -365,11 +462,11 @@ class WIO_Attachment {
365
  $extra_data->set_main_optimized_data( $main_optimized_data );
366
  }
367
  }
368
-
369
  $thumbnails_processed = true;
370
  $thumbnails = (array) $extra_data->get_thumbnails_optimized_data();
371
  $thumbnails = json_decode( json_encode( $thumbnails ), true ); // рекурсивная конвертация объекта в массив
372
-
373
  if ( is_array( $thumbnails['thumbnails'] ) ) {
374
  foreach ( $thumbnails['thumbnails'] as &$thumbnail_optimized_data ) {
375
  if ( ! $thumbnail_optimized_data['optimized_img_url'] ) {
@@ -383,7 +480,7 @@ class WIO_Attachment {
383
  }
384
  $extra_data->set_thumbnails_optimized_data( $thumbnails );
385
  }
386
-
387
  // когда все файлы получены - сохраняем и возвращаем результат
388
  if ( $main_image_url && $thumbnails_processed ) {
389
  $original_size = 0;
@@ -391,80 +488,80 @@ class WIO_Attachment {
391
  $thumbnails_count = 0;
392
  $original_main_size = filesize( $this->get( 'path' ) );
393
  $original_size = $original_size + $original_main_size;
394
-
395
- $this->replaceOriginalFile( array(
396
  'optimized_img_url' => $main_image_url,
397
- ) );
398
-
399
  clearstatcache();
400
-
401
  $optimized_main_size = filesize( $this->get( 'path' ) );
402
-
403
  // при отрицательной оптимизации ставим значение оригинала
404
  if ( $optimized_main_size > $original_main_size ) {
405
  $optimized_main_size = $original_main_size;
406
  }
407
-
408
  $optimized_size = $optimized_size + $optimized_main_size;
409
-
410
  if ( is_array( $thumbnails['thumbnails'] ) ) {
411
  foreach ( $thumbnails['thumbnails'] as $thumbnail_size => $thumbnail ) {
412
  $thumbnail_file = $this->getImageSizePath( $thumbnail_size );
413
  $original_thumbnail_size = filesize( $thumbnail_file );
414
  $original_size = $original_size + $original_thumbnail_size;
415
-
416
- $this->replaceOriginalFile( array(
417
  'optimized_img_url' => $thumbnail['optimized_img_url'],
418
- ), $thumbnail_size );
419
-
420
  clearstatcache();
421
-
422
  $optimized_thumbnail_size = filesize( $thumbnail_file );
423
-
424
  // при отрицательной оптимизации ставим значение оригинала
425
  if ( $optimized_thumbnail_size > $original_thumbnail_size ) {
426
  $optimized_thumbnail_size = $original_thumbnail_size;
427
  }
428
-
429
  $optimized_size = $optimized_size + $optimized_thumbnail_size;
430
-
431
  $thumbnails_count ++;
432
  }
433
  }
434
-
435
  $mime_type = '';
436
  if ( function_exists( 'wp_get_image_mime' ) ) {
437
  $mime_type = wp_get_image_mime( $this->get( 'path' ) );
438
  }
439
-
440
- $optimization_data->configure( array(
441
  'final_size' => $optimized_size,
442
  'original_size' => $original_size,
443
  'result_status' => 'success',
444
  'original_mime_type' => $mime_type,
445
  'final_mime_type' => $mime_type,
446
- ) );
447
-
448
  $extra_data->set_original_main_size( $original_main_size );
449
  $extra_data->set_thumbnails_count( $thumbnails_count );
450
-
451
  // удаляем промежуточные данные
452
  $extra_data->set_main_optimized_data( null );
453
  $extra_data->set_thumbnails_optimized_data( null );
454
  $extra_data->set_main_optimized_data( null );
455
-
456
  $results['optimized_count'] = 1;
457
  $results['original_size'] = $original_size;
458
  $results['optimized_size'] = $optimized_size;
459
-
460
  unset( $results['processing'] );
461
  }
462
  $optimization_data->set_extra_data( $extra_data );
463
  $optimization_data->save();
464
-
465
  return $results;
466
  }
467
-
468
  /**
469
  * Метод проверяет, оптимизирован ли аттачмент
470
  *
@@ -475,10 +572,10 @@ class WIO_Attachment {
475
  if ( $optimization_data->is_optimized() ) {
476
  return true;
477
  }
478
-
479
  return false;
480
  }
481
-
482
  /**
483
  * Возвращает все размеры аттачмента, которые нужно оптимизировать
484
  *
@@ -486,16 +583,16 @@ class WIO_Attachment {
486
  */
487
  public function getAllowedSizes() {
488
  $allowed_sizes = WRIO_Plugin::app()->getPopulateOption( 'allowed_sizes_thumbnail', 'thumbnail,medium' );
489
-
490
  if ( ! $allowed_sizes ) {
491
  return false;
492
  }
493
-
494
  $allowed_sizes = explode( ',', $allowed_sizes );
495
-
496
  return $allowed_sizes;
497
  }
498
-
499
  /**
500
  * Оптимизация других размеров аттачмента.
501
  *
@@ -503,47 +600,47 @@ class WIO_Attachment {
503
  */
504
  public function optimizeImageSizes() {
505
  $allowed_sizes = $this->getAllowedSizes();
506
-
507
  if ( $allowed_sizes === false ) {
508
- return array();
509
  }
510
-
511
  $image_processor = WIO_OptimizationTools::getImageProcessor();
512
  $quality = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_level', 'normal' );
513
-
514
  if ( $quality == 'custom' ) {
515
  $custom_quality = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_level_custom', 100 );
516
  $quality = intval( $custom_quality );
517
  }
518
-
519
  $exif = WRIO_Plugin::app()->getPopulateOption( 'save_exif_data', false );
520
-
521
  $original_size = 0;
522
  $optimized_size = 0;
523
  $errors_count = 0;
524
  $optimized_count = 0;
525
- $thumbnails = array();
526
-
527
  foreach ( $allowed_sizes as $image_size ) {
528
  $url = $this->getImageSizeUrl( $image_size );
529
  $path = $this->getImageSizePath( $image_size );
530
-
531
  if ( ! $url || ! $path ) {
532
  continue;
533
  }
534
-
535
  $original_file_size = 0;
536
-
537
  if ( is_file( $path ) ) {
538
  $original_file_size = filesize( $path );
539
  }
540
-
541
- $optimized_img_data = $image_processor->process( array(
542
  'image_url' => $url,
543
  'image_path' => $path,
544
  'quality' => $image_processor->quality( $quality ),
545
  'save_exif' => $exif,
546
- ) );
547
  // проверяем на ошибку
548
  if ( is_wp_error( $optimized_img_data ) ) {
549
  $errors_count ++;
@@ -558,94 +655,94 @@ class WIO_Attachment {
558
  if ( ! $optimized_img_data['src_size'] ) {
559
  $optimized_img_data['src_size'] = $original_file_size;
560
  }
561
-
562
  // при отрицательной оптимизации ставим значение оригинала
563
  if ( $optimized_img_data['optimized_size'] > $original_file_size ) {
564
  $optimized_img_data['optimized_size'] = $original_file_size;
565
  }
566
-
567
  $thumbnails[ $image_size ] = $optimized_img_data;
568
-
569
  //просчитываем статистику
570
  $original_size += $optimized_img_data['src_size'];
571
  $optimized_size += $optimized_img_data['optimized_size'];
572
  $optimized_count ++;
573
  }
574
  }
575
-
576
- return array(
577
  'errors_count' => $errors_count,
578
  'original_size' => $original_size,
579
  'optimized_size' => $optimized_size,
580
  'thumbnails_count' => $optimized_count,
581
  'thumbnails' => $thumbnails,
582
- );
583
  }
584
-
585
  /**
586
  * Возвращает путь.
587
  *
588
- * @param string $image_size Размер(thumbnail, medium ... )
589
  *
590
  * @return string
591
  */
592
  public function getPath( $image_size = '' ) {
593
-
594
  if ( empty( $image_size ) ) {
595
  $path = $this->path;
596
  } else {
597
  $path = $this->getImageSizePath( $image_size );
598
  }
599
-
600
  return $path;
601
  }
602
-
603
  /**
604
  * Заменяет оригинальный файл на оптимизированный.
605
  *
606
- * @param array $optimized_img_data Hезультат оптимизации ввиде массива данных.
607
- * @param string $image_size Размер (thumbnail, medium ... )
608
  *
609
  * @return bool
610
  */
611
  public function replaceOriginalFile( $optimized_img_data, $image_size = '' ) {
612
-
613
  $optimized_img_url = $optimized_img_data['optimized_img_url'];
614
-
615
  if ( isset( $optimized_img_data['not_need_download'] ) && (bool) $optimized_img_data['not_need_download'] ) {
616
  $optimized_file = $optimized_img_url;
617
  } else {
618
  $optimized_file = $this->remoteDownloadImage( $optimized_img_url );
619
  }
620
-
621
  if ( empty( $optimized_file ) ) {
622
  WRIO_Logger::error( sprintf( 'Unable to replace original image with new as failed to download %s', $optimized_img_url ) );
623
-
624
  return false;
625
  }
626
-
627
  if ( isset( $optimized_img_data['not_need_replace'] ) && $optimized_img_data['not_need_replace'] ) {
628
  // если картинка уже оптимизирована и провайдер её не может уменьшить - он может вернуть положительный ответ, но без самой картинки. В таком случае ничего заменять не надо
629
  return true;
630
  }
631
-
632
  $attachment_size_path = $this->getPath( $image_size );
633
-
634
  if ( ! is_file( $attachment_size_path ) ) {
635
  return false;
636
  }
637
-
638
  $bytes = @file_put_contents( $attachment_size_path, $optimized_file );
639
-
640
  if ( $bytes === false ) {
641
  WRIO_Logger::error( sprintf( 'Failed to put new image\'s %s content to %s as file_put_contents() failed', $optimized_img_url, $attachment_size_path ) );
642
-
643
  return false;
644
  }
645
-
646
  return true;
647
  }
648
-
649
  /**
650
  * Скачивание изображения с удалённого сервера
651
  *
@@ -654,44 +751,44 @@ class WIO_Attachment {
654
  * @return string|null Image content on success, NULL on failure.
655
  */
656
  protected function remoteDownloadImage( $url ) {
657
-
658
  if ( ! function_exists( 'curl_version' ) ) {
659
  $content = @file_get_contents( $url );
660
-
661
  if ( $content === false ) {
662
  WRIO_Logger::error( sprintf( 'Failed to get content of "%s" using file_get_contents()', $url ) );
663
-
664
  return null;
665
  }
666
-
667
  return $content;
668
  }
669
-
670
  $ch = curl_init();
671
  curl_setopt( $ch, CURLOPT_HEADER, 0 );
672
  curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
673
  curl_setopt( $ch, CURLOPT_URL, $url );
674
-
675
  $image_body = curl_exec( $ch );
676
  $http_code = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
677
  if ( $http_code != '200' ) {
678
  $image_body = false;
679
  }
680
  curl_close( $ch );
681
-
682
  if ( $image_body === false ) {
683
  WRIO_Logger::error( sprintf( 'Failed to get content of "%s" using curl_exec()', $url ) );
684
-
685
  return null;
686
  }
687
-
688
  return $image_body;
689
  }
690
-
691
  /**
692
  * Возвращает свойство аттачмента
693
  *
694
- * @param string $property имя свойства
695
  *
696
  * @return mixed
697
  */
@@ -699,14 +796,14 @@ class WIO_Attachment {
699
  if ( isset( $this->$property ) ) {
700
  return $this->$property;
701
  }
702
-
703
  return false;
704
  }
705
-
706
  /**
707
  * Возвращает URL изображения по указанному размеру
708
  *
709
- * @param string $size - размер изображения(thumbnail,medium,large...)
710
  *
711
  * @return string|null
712
  */
@@ -714,17 +811,17 @@ class WIO_Attachment {
714
  if ( ! isset( $this->attachment_meta['sizes'][ $size ] ) ) {
715
  return null;
716
  }
717
-
718
  $file = $this->attachment_meta['sizes'][ $size ]['file'];
719
  $url = str_replace( wp_basename( $this->url ), $file, $this->url );
720
-
721
  return $url;
722
  }
723
-
724
  /**
725
  * Возвращает путь к изображению по указанному размеру.
726
  *
727
- * @param string $size Размер изображения (thumbnail, medium, large ...)
728
  *
729
  * @return string Путь до изображения.
730
  */
@@ -732,13 +829,13 @@ class WIO_Attachment {
732
  if ( ! isset( $this->attachment_meta['sizes'][ $size ] ) ) {
733
  return null;
734
  }
735
-
736
  $file = $this->attachment_meta['sizes'][ $size ]['file'];
737
  $path = str_replace( wp_basename( $this->path ), $file, $this->path );
738
-
739
  return $path;
740
  }
741
-
742
  /**
743
  * Проверка необходимости делать изменение размера.
744
  *
@@ -746,18 +843,18 @@ class WIO_Attachment {
746
  */
747
  protected function isNeedResize() {
748
  $resize_large_images = WRIO_Plugin::app()->getPopulateOption( 'resize_larger', true );
749
-
750
  if ( ! $resize_large_images ) {
751
  return false;
752
  }
753
-
754
  $resize_larger_w = (int) WRIO_Plugin::app()->getPopulateOption( 'resize_larger_w', 1600 );
755
  $resize_larger_h = (int) WRIO_Plugin::app()->getPopulateOption( 'resize_larger_h', 1600 );
756
-
757
  if ( ! $resize_larger_w && ! $resize_larger_h ) {
758
  return false;
759
  }
760
-
761
  // если ширина и высота установлены и > 0
762
  if ( $this->attachment_meta['width'] >= $this->attachment_meta['height'] ) {
763
  $larger_side = $this->attachment_meta['width'];
@@ -780,10 +877,10 @@ class WIO_Attachment {
780
  if ( $larger_side <= $resize_larger_side ) {
781
  return false;
782
  }
783
-
784
  return true;
785
  }
786
-
787
  /**
788
  * Возвращает метаданные аттачмента
789
  *
@@ -792,7 +889,7 @@ class WIO_Attachment {
792
  public function getMetaData() {
793
  return $this->attachment_meta;
794
  }
795
-
796
  /**
797
  * Изменяет размер изображения до заданного в настройках размера.
798
  *
@@ -801,19 +898,19 @@ class WIO_Attachment {
801
  protected function resize() {
802
  $resize_larger_h = (int) WRIO_Plugin::app()->getPopulateOption( 'resize_larger_h', 1600 );
803
  $resize_larger_w = (int) WRIO_Plugin::app()->getPopulateOption( 'resize_larger_w', 1600 );
804
-
805
  $image = wp_get_image_editor( $this->path );
806
-
807
  if ( is_wp_error( $image ) ) {
808
  WRIO_Logger::error( sprintf( 'Failed to get image edit via wp_get_image_editor(), error: "%s"', $image->get_error_message() ) );
809
-
810
  return false;
811
  }
812
-
813
  $current_size = $image->get_size();
814
  $new_width = 0;
815
  $new_height = 0;
816
-
817
  // если обе стороны заданы
818
  if ( $resize_larger_h && $resize_larger_w ) {
819
  // определяем большую сторону и по ней маштабируем
@@ -837,38 +934,38 @@ class WIO_Attachment {
837
  $new_height = round( $current_size['height'] * $new_width / $current_size['width'] );
838
  }
839
  }
840
-
841
  $nl = PHP_EOL;
842
  $log_message = sprintf( "\tResize from: %sx%s to %sx%s", $current_size['width'], $current_size['height'], $new_width, $new_height ) . $nl;
843
  $log_message .= sprintf( "\tLarger resize from %sx%s", $resize_larger_w, $resize_larger_h ) . $nl;
844
  $log_message .= sprintf( "\tAbsolute path: %s", $this->path ) . $nl;
845
-
846
  $resize_result = $image->resize( $new_width, $new_height, false );
847
-
848
  if ( is_wp_error( $resize_result ) ) {
849
  $this->writeLog( sprintf( 'Resize error: %s. Details: %s', $resize_result->get_error_messages(), $log_message ) );
850
-
851
  return false;
852
  }
853
-
854
  $save_result = $image->save( $this->path );
855
-
856
  if ( is_wp_error( $save_result ) ) {
857
  $this->writeLog( sprintf( 'Failed to save resized error in db: %s, Details: %s', $save_result->get_error_messages(), $log_message ) );
858
-
859
  return false;
860
  }
861
-
862
  $this->attachment_meta['width'] = $new_width;
863
  $this->attachment_meta['height'] = $new_height;
864
  $this->attachment_meta['old_width'] = $current_size['width'];
865
  $this->attachment_meta['old_height'] = $current_size['height'];
866
-
867
  wp_update_attachment_metadata( $this->id, $this->attachment_meta );
868
-
869
  return true;
870
  }
871
-
872
  /**
873
  * Делает резервную копию
874
  *
@@ -876,10 +973,10 @@ class WIO_Attachment {
876
  */
877
  protected function backup() {
878
  $backup = WIO_Backup::get_instance();
879
-
880
  return $backup->backupAttachment( $this );
881
  }
882
-
883
  /**
884
  * Восстанавливает файлы из резервной копии
885
  *
@@ -887,7 +984,7 @@ class WIO_Attachment {
887
  */
888
  public function restore() {
889
  $backup = WIO_Backup::get_instance();
890
-
891
  return $backup->restoreAttachment( $this );
892
  }
893
  }
8
  /**
9
  * Класс для работы с WordPress attachment.
10
  *
11
+ * @author Eugene Jokerov <jokerov@gmail.com>
12
  * @copyright (c) 2018, Webcraftic
13
+ * @version 1.0
14
  */
15
  class WIO_Attachment {
16
+
17
  /**
18
  * @var int
19
  */
20
  private $id;
21
+
22
+
23
  /**
24
  * @var array meta-данные
25
  */
26
  private $attachment_meta;
27
+
28
  /**
29
  * @var array массив с данными о папке uploads
30
  */
31
  private $wp_upload_dir;
32
+
33
  /**
34
  * @var string
35
  */
36
  private $url;
37
+
38
  /**
39
  * @var string
40
  */
41
  private $path;
42
+
43
  /**
44
  * @var RIO_Process_Queue
45
  */
46
  private $optimization_data;
47
+
48
  /**
49
  * Инициализация аттачмента
50
  *
51
+ * @param int $attachment_id Номер аттачмента из медиабиблиотеки
52
+ * @param array|false $attachment_meta метаданные аттачмента. Ключи массива аналогичны функции wp_get_attachment_metadata
53
  */
54
  public function __construct( $attachment_id, $attachment_meta = false ) {
55
  $this->id = $attachment_id;
56
  $this->wp_upload_dir = wp_upload_dir();
57
  $this->attachment_meta = $attachment_meta;
58
+
59
  if ( ! $attachment_meta ) {
60
  // some meta can be missing due to: https://wordpress.stackexchange.com/q/330174/149161
61
  $this->attachment_meta = wp_get_attachment_metadata( $this->id );
62
  }
63
+
64
+ $this->set_paths();
65
+ }
66
+
67
+ /**
68
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
69
+ * @since 1.3.9
70
+ * @return bool
71
+ */
72
+ public function isset_attachment_meta() {
73
+ return $this->attachment_meta && isset( $this->attachment_meta['file'] );
74
+ }
75
+
76
+ /**
77
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
78
+ * @since 1.3.9
79
+ */
80
+ public function set_paths() {
81
+ if ( ! $this->isset_attachment_meta() ) {
82
+ return;
83
  }
84
+
85
+ $this->url = trailingslashit( $this->wp_upload_dir['baseurl'] ) . $this->attachment_meta['file'];
86
+ $this->path = wp_normalize_path( trailingslashit( $this->wp_upload_dir['basedir'] ) . $this->attachment_meta['file'] );
87
  }
88
+
89
  /**
90
  * Актуализирует мета данные аттачмента и загружает актуальные мета данные и данные по оптимизации из базы.
91
  */
92
+ public function reload( $attachment_meta = [] ) {
93
+ if ( empty( $attachment_meta ) ) {
94
+ $attachment_meta = wp_get_attachment_metadata( $this->id );
95
+ }
96
+ $this->attachment_meta = $attachment_meta;
97
+ $this->optimization_data = new RIO_Process_Queue( [
98
  'object_id' => $this->id,
99
  'object_name' => '',
100
  'item_type' => 'attachment',
101
+ ] );
102
  $this->optimization_data->load();
103
+ $this->set_paths();
104
  }
105
+
106
+ /**
107
+ * Fallback to get attachment meta it can be empty when WordPress failed to create it or invocation
108
+ * of method was produced too soon.
109
+ *
110
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
111
+ * @since 1.3.9
112
+ * @return bool
113
+ */
114
+ public function regenerate_metadata() {
115
+ if ( $this->isset_attachment_meta() ) {
116
+ return true;
117
+ }
118
+
119
+ WRIO_Logger::info( sprintf( 'Try regenerate metadata for attachment #%d', $this->id ) );
120
+
121
+ // Need to remove this filter, as it would start recursion
122
+ remove_filter( 'wp_generate_attachment_metadata', 'WRIO_Media_Library::optimize_after_upload' );
123
+
124
+ $file_path = get_attached_file( $this->id );
125
+
126
+ if ( empty( $file_path ) ) {
127
+ $attachment = get_post( $this->id );
128
+
129
+ if ( empty( $attachment ) || 'attachment' !== $attachment->post_type ) {
130
+ return false;
131
+ }
132
+
133
+ $file_path = wrio_convert_url_to_abs_path( $attachment->guid );
134
+ }
135
+
136
+ if ( empty( $file_path ) || ! file_exists( $file_path ) ) {
137
+ WRIO_Logger::info( sprintf( 'Failed regenerate attachment meta data. Attachment file (%s) doesn\'t exists!', $file_path ) );
138
+
139
+ return false;
140
+ }
141
+
142
+ $attachment_meta = wp_generate_attachment_metadata( $this->id, $file_path );
143
+
144
+ if ( empty( $attachment_meta ) ) {
145
+ WRIO_Logger::error( sprintf( 'Failed regenerate meta data for attachment file (%s).', $file_path ) );
146
+
147
+ return false;
148
+ }
149
+
150
+ WRIO_Logger::debug( sprintf( 'Generated metadata: %s', var_export( $attachment_meta, true ) ) );
151
+
152
+ # Updating metadata in database
153
+ wp_update_attachment_metadata( $this->id, $attachment_meta );
154
+
155
+ $this->reload( $attachment_meta );
156
+
157
+ add_filter( 'wp_generate_attachment_metadata', 'WRIO_Media_Library::optimize_after_upload', 10, 2 );
158
+
159
+ WRIO_Logger::info( sprintf( 'Finish regenerate metadata for attachment #%d!', $this->id ) );
160
+
161
+ return true;
162
+ }
163
+
164
  /**
165
  * Добавляем сообщение в лог файл.
166
  *
167
+ * @param string $message Текст сообщения об ошибке.
168
  */
169
  public function writeLog( $message ) {
170
+
171
  $char = "\t-> ";
172
  $nl = PHP_EOL;
173
+
174
  $error = sprintf( 'Error to optimize attachment (ID: #%s). Message: "%s"', $this->id, trim( $message ) ) . $nl;
175
  $error .= $char . sprintf( "Attachment optimized? %s", ( $this->isOptimized() ? 'Yes' : 'No' ) ) . $nl;
176
  $error .= $char . sprintf( "Should be resized? %s", ( $this->isNeedResize() ? 'Yes' : 'No' ) ) . $nl;
177
  $error .= $char . sprintf( "Original size: %sx%s", $this->attachment_meta['width'], $this->attachment_meta['height'] ) . $nl;
178
  $error .= $char . sprintf( "Relative path: %s", $this->attachment_meta['file'] ) . $nl;
179
  $error .= $char . sprintf( "Server used: %s", WRIO_Plugin::app()->getPopulateOption( 'image_optimization_server', 'server_1' ) ) . $nl;
180
+
181
  if ( ! empty( $this->attachment_meta['sizes'] ) ) {
182
  $error .= $char . ' Additional sizes:' . $nl;
183
  foreach ( $this->attachment_meta['sizes'] as $size_type => $size_info ) {
184
  $error .= "\t" . $char . sprintf( 'Type: %s, size: %sx%s, MIME type: %s', $size_type, $size_info['width'], $size_info['height'], $size_info['mime-type'] ) . $nl;
185
  }
186
  }
187
+
188
  WRIO_Logger::error( $error );
189
  }
190
+
191
  /**
192
  * Возвращает объект с информацией об оптимизации
193
  *
195
  */
196
  public function getOptimizationData() {
197
  if ( ! isset( $optimization_data ) ) {
198
+ $this->optimization_data = new RIO_Process_Queue( [
199
  'object_id' => $this->id,
200
  'object_name' => '',
201
  'item_type' => 'attachment',
202
+ ] );
203
  $this->optimization_data->load();
204
  }
205
+
206
  return $this->optimization_data;
207
  }
208
+
209
  /**
210
  * Оптимизация аттачмента.
211
  *
212
+ * @param string $optimization_level Уровень оптимизации изображения.
213
  *
214
  * @return array
215
  */
216
  public function optimize( $optimization_level = '' ) {
217
+ $optimize_results = [
218
  'original_size' => 0,
219
  'optimized_size' => 0,
220
+ ];
221
+
222
  if ( empty( $optimization_level ) ) {
223
  $optimization_level = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_level', 'normal' );
224
  }
225
+
226
  if ( $optimization_level == 'custom' ) {
227
  $custom_quality = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_level_custom', 100 );
228
  $optimization_level = intval( $custom_quality );
229
  }
230
+
231
  $optimization_data = $this->getOptimizationData();
232
+ $results = [
233
  'original_size' => 0,
234
  'final_size' => 0,
235
  'original_mime_type' => '',
236
  'final_mime_type' => '',
237
+ ];
238
  $results['processing_level'] = $optimization_level;
239
+
240
+ # The path may be empty because no metadata has been created for the image.
241
+ # We should try to create image metadata again.
242
+ if ( ! $this->isset_attachment_meta() ) {
243
+ WRIO_Logger::warning( sprintf( 'Attachment #%d doesn\'t have metadata.', $this->id ) );
244
+
245
+ $this->regenerate_metadata();
246
+ }
247
+
248
+ if ( empty( $this->path ) || ! file_exists( $this->path ) ) {
249
  $results['result_status'] = 'error';
250
+
251
+ $error_message = __( 'Attachment cannot be optimized.', 'robin-image-optimizer' );
252
+
253
+ if ( empty( $this->path ) ) {
254
+ $error_message .= ' ' . sprintf( __( 'Attachment #%d doesn\'t have metadata, the image may be damaged.', 'robin-image-optimizer' ), $this->id );
255
+ } else {
256
+ $error_message .= ' ' . sprintf( __( 'File "(%s)" doesn\'t exist', 'robin-image-optimizer' ), $this->path );
257
+ }
258
+
259
+ $extra_data = [
260
  'error' => 'path',
261
+ 'error_msg' => $error_message,
262
+ ];
263
+
264
+ $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
265
  $optimization_data->configure( $results );
266
  $optimization_data->save();
267
+
268
  WRIO_Logger::error( sprintf( 'Failed to find original attachment #%s located in %s. Skipping optimization. This may be caused due to bug in %s function, which returns false for attachment meta', $this->id, empty( $path ) ? '*empty path*' : $path, 'wp_get_attachment_metadata()' ) );
269
+
270
  return $optimize_results;
271
  }
272
+
273
  // сначала бекапим
274
  $is_image_backuped = $this->backup();
275
+
276
  if ( is_wp_error( $is_image_backuped ) ) {
277
  $error_msg = $is_image_backuped->get_error_message();
278
  $this->writeLog( $error_msg );
279
+
280
  $results['result_status'] = 'error';
281
+ $extra_data = [
282
  'error' => 'backup',
283
  'error_msg' => 'Failed to backup',
284
+ ];
285
  $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
286
  $optimization_data->configure( $results );
287
  $optimization_data->save();
288
+
289
  WRIO_Logger::error( sprintf( 'Failed to make backup of original attachment #%s. Skipping optimization.', $this->id ) );
290
+
291
  return $optimize_results;
292
  }
293
+
294
  $results['is_backed_up'] = $is_image_backuped;
295
+
296
+ $original_main_size = filesize( $this->path );
297
+
298
  // если файл большой - изменяем размер
299
  if ( $this->isNeedResize() ) {
300
  $this->resize();
301
  }
302
+
303
  $image_processor = WIO_OptimizationTools::getImageProcessor();
304
+
305
  clearstatcache(); // на всякий случай очистим кеш файловой статистики
306
+
307
+ $optimized_img_data = $image_processor->process( [
308
  'image_url' => $this->get( 'url' ),
309
  'image_path' => $this->get( 'path' ),
310
  'quality' => $image_processor->quality( $optimization_level ),
311
  'save_exif' => WRIO_Plugin::app()->getPopulateOption( 'save_exif_data', false ),
312
+ ] );
313
+
314
  // проверяем на ошибку
315
  if ( is_wp_error( $optimized_img_data ) ) {
316
  $error_msg = $optimized_img_data->get_error_message();
317
  $this->writeLog( $error_msg );
318
+
319
  $results['result_status'] = 'error';
320
+
321
+ $extra_data = [
322
  'error' => 'optimization',
323
  'error_msg' => $error_msg,
324
+ ];
325
+
326
  $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
327
+
328
  $optimization_data->configure( $results );
329
  $optimization_data->save();
330
+
331
  WRIO_Logger::error( sprintf( 'Failed to process (url: %s, path: %s, quality: %s) as error was returned: %s', $this->get( 'url' ), $this->get( 'path' ), $image_processor->quality( $optimization_level ), $error_msg ) );
332
+
333
  return $optimize_results;
334
  }
335
+
336
  $results['original_mime_type'] = '';
337
  $results['final_mime_type'] = '';
338
+
339
  // отложенная оптимизация
340
  if ( isset( $optimized_img_data['status'] ) && $optimized_img_data['status'] == 'processing' ) {
341
  $results['result_status'] = 'processing';
342
  $results['original_size'] = 0;
343
  $results['final_size'] = 0;
344
+
345
+ $extra_data = [
346
  'main_optimized_data' => $optimized_img_data,
347
  'thumbnails_optimized_data' => $this->optimizeImageSizes(),
348
+ ];
349
+
350
  $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
351
+
352
  $optimization_data->configure( $results );
353
  $optimization_data->save();
354
  $optimize_results['processing'] = 1;
355
+
356
  return $optimize_results;
357
  }
358
+
359
  //скачиваем и заменяем главную картинку
360
  $image_downloaded = $this->replaceOriginalFile( $optimized_img_data );
361
+
362
  // некоторые провайдеры не отдают оптимизированный размер, поэтому после замены файла получаем его сами
363
  if ( ! $optimized_img_data['optimized_size'] ) {
364
  clearstatcache();
365
  $optimized_img_data['optimized_size'] = filesize( $this->get( 'path' ) );
366
  }
367
+
368
  // при отрицательной оптимизации ставим значение оригинала
369
  if ( $optimized_img_data['optimized_size'] > $original_main_size ) {
370
  $optimized_img_data['optimized_size'] = $original_main_size;
371
  }
372
+
373
  if ( $image_downloaded ) {
374
  //просчитываем статистику
375
  $optimize_results['original_size'] += $original_main_size;
376
  $optimize_results['optimized_size'] += $optimized_img_data['optimized_size'];
377
  $thumbnails_count = 0;
378
+
379
  // оптимизируем дополнительные размеры
380
  $optimized_img_sizes_data = $this->optimizeImageSizes();
381
+
382
  // добавляем к статистике данные по оптимизации доп размеров
383
  if ( ! empty( $optimized_img_sizes_data ) ) {
384
  $optimize_results['original_size'] += $optimized_img_sizes_data['original_size'];
385
  $optimize_results['optimized_size'] += $optimized_img_sizes_data['optimized_size'];
386
  $thumbnails_count = $optimized_img_sizes_data['thumbnails_count'];
387
  }
388
+
389
  $results['result_status'] = 'success';
390
  $results['final_size'] = $optimize_results['optimized_size'];
391
  $results['original_size'] = $optimize_results['original_size'];
392
+
393
+ $extra_data = [
394
  'thumbnails_count' => $thumbnails_count,
395
  'original_main_size' => $original_main_size,
396
+ ];
397
+
398
  $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
399
  $mime_type = '';
400
+
401
  if ( function_exists( 'wp_get_image_mime' ) ) {
402
  $mime_type = wp_get_image_mime( $this->get( 'path' ) );
403
  } else {
404
  WRIO_Logger::error( 'App is missing wp_get_image_mime() function, unable to get MIME type' );
405
  }
406
+
407
  $results['original_mime_type'] = $mime_type;
408
  $results['final_mime_type'] = $mime_type;
409
  $optimization_data->configure( $results );
410
  } else {
411
  $error_msg = 'Failed to get optimized image from remote server';
412
  $this->writeLog( $error_msg );
413
+
414
  $results['result_status'] = 'error';
415
+
416
+ $extra_data = [
417
  'error' => 'download',
418
  'error_msg' => $error_msg,
419
+ ];
420
+
421
  $results['extra_data'] = new RIO_Attachment_Extra_Data( $extra_data );
422
  $optimization_data->configure( $results );
423
  }
424
+
425
  $optimization_data->save();
426
+
427
  return $optimize_results;
428
  }
429
+
430
  /**
431
  * Отложенная оптимизация аттачмента
432
  *
433
  * @return bool|array
434
  */
435
  public function deferredOptimization() {
436
+ $results = [
437
  'original_size' => 0,
438
  'optimized_size' => 0,
439
  'optimized_count' => 0,
440
  'processing' => 1,
441
+ ];
442
+
443
  $image_processor = WIO_OptimizationTools::getImageProcessor();
444
  $optimization_data = $this->getOptimizationData();
445
+
446
  if ( $optimization_data->get_result_status() != 'processing' ) {
447
  return false;
448
  }
449
+
450
  // проверяем главную картинку
451
  /**
452
  * @var RIO_Attachment_Extra_Data $extra_data
454
  $extra_data = $optimization_data->get_extra_data();
455
  $main_optimized_data = $extra_data->get_main_optimized_data();
456
  $main_image_url = '';
457
+
458
  if ( ! $main_optimized_data['optimized_img_url'] ) {
459
  $main_image_url = $image_processor->checkDeferredOptimization( $main_optimized_data );
460
  if ( $main_image_url ) {
462
  $extra_data->set_main_optimized_data( $main_optimized_data );
463
  }
464
  }
465
+
466
  $thumbnails_processed = true;
467
  $thumbnails = (array) $extra_data->get_thumbnails_optimized_data();
468
  $thumbnails = json_decode( json_encode( $thumbnails ), true ); // рекурсивная конвертация объекта в массив
469
+
470
  if ( is_array( $thumbnails['thumbnails'] ) ) {
471
  foreach ( $thumbnails['thumbnails'] as &$thumbnail_optimized_data ) {
472
  if ( ! $thumbnail_optimized_data['optimized_img_url'] ) {
480
  }
481
  $extra_data->set_thumbnails_optimized_data( $thumbnails );
482
  }
483
+
484
  // когда все файлы получены - сохраняем и возвращаем результат
485
  if ( $main_image_url && $thumbnails_processed ) {
486
  $original_size = 0;
488
  $thumbnails_count = 0;
489
  $original_main_size = filesize( $this->get( 'path' ) );
490
  $original_size = $original_size + $original_main_size;
491
+
492
+ $this->replaceOriginalFile( [
493
  'optimized_img_url' => $main_image_url,
494
+ ] );
495
+
496
  clearstatcache();
497
+
498
  $optimized_main_size = filesize( $this->get( 'path' ) );
499
+
500
  // при отрицательной оптимизации ставим значение оригинала
501
  if ( $optimized_main_size > $original_main_size ) {
502
  $optimized_main_size = $original_main_size;
503
  }
504
+
505
  $optimized_size = $optimized_size + $optimized_main_size;
506
+
507
  if ( is_array( $thumbnails['thumbnails'] ) ) {
508
  foreach ( $thumbnails['thumbnails'] as $thumbnail_size => $thumbnail ) {
509
  $thumbnail_file = $this->getImageSizePath( $thumbnail_size );
510
  $original_thumbnail_size = filesize( $thumbnail_file );
511
  $original_size = $original_size + $original_thumbnail_size;
512
+
513
+ $this->replaceOriginalFile( [
514
  'optimized_img_url' => $thumbnail['optimized_img_url'],
515
+ ], $thumbnail_size );
516
+
517
  clearstatcache();
518
+
519
  $optimized_thumbnail_size = filesize( $thumbnail_file );
520
+
521
  // при отрицательной оптимизации ставим значение оригинала
522
  if ( $optimized_thumbnail_size > $original_thumbnail_size ) {
523
  $optimized_thumbnail_size = $original_thumbnail_size;
524
  }
525
+
526
  $optimized_size = $optimized_size + $optimized_thumbnail_size;
527
+
528
  $thumbnails_count ++;
529
  }
530
  }
531
+
532
  $mime_type = '';
533
  if ( function_exists( 'wp_get_image_mime' ) ) {
534
  $mime_type = wp_get_image_mime( $this->get( 'path' ) );
535
  }
536
+
537
+ $optimization_data->configure( [
538
  'final_size' => $optimized_size,
539
  'original_size' => $original_size,
540
  'result_status' => 'success',
541
  'original_mime_type' => $mime_type,
542
  'final_mime_type' => $mime_type,
543
+ ] );
544
+
545
  $extra_data->set_original_main_size( $original_main_size );
546
  $extra_data->set_thumbnails_count( $thumbnails_count );
547
+
548
  // удаляем промежуточные данные
549
  $extra_data->set_main_optimized_data( null );
550
  $extra_data->set_thumbnails_optimized_data( null );
551
  $extra_data->set_main_optimized_data( null );
552
+
553
  $results['optimized_count'] = 1;
554
  $results['original_size'] = $original_size;
555
  $results['optimized_size'] = $optimized_size;
556
+
557
  unset( $results['processing'] );
558
  }
559
  $optimization_data->set_extra_data( $extra_data );
560
  $optimization_data->save();
561
+
562
  return $results;
563
  }
564
+
565
  /**
566
  * Метод проверяет, оптимизирован ли аттачмент
567
  *
572
  if ( $optimization_data->is_optimized() ) {
573
  return true;
574
  }
575
+
576
  return false;
577
  }
578
+
579
  /**
580
  * Возвращает все размеры аттачмента, которые нужно оптимизировать
581
  *
583
  */
584
  public function getAllowedSizes() {
585
  $allowed_sizes = WRIO_Plugin::app()->getPopulateOption( 'allowed_sizes_thumbnail', 'thumbnail,medium' );
586
+
587
  if ( ! $allowed_sizes ) {
588
  return false;
589
  }
590
+
591
  $allowed_sizes = explode( ',', $allowed_sizes );
592
+
593
  return $allowed_sizes;
594
  }
595
+
596
  /**
597
  * Оптимизация других размеров аттачмента.
598
  *
600
  */
601
  public function optimizeImageSizes() {
602
  $allowed_sizes = $this->getAllowedSizes();
603
+
604
  if ( $allowed_sizes === false ) {
605
+ return [];
606
  }
607
+
608
  $image_processor = WIO_OptimizationTools::getImageProcessor();
609
  $quality = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_level', 'normal' );
610
+
611
  if ( $quality == 'custom' ) {
612
  $custom_quality = WRIO_Plugin::app()->getPopulateOption( 'image_optimization_level_custom', 100 );
613
  $quality = intval( $custom_quality );
614
  }
615
+
616
  $exif = WRIO_Plugin::app()->getPopulateOption( 'save_exif_data', false );
617
+
618
  $original_size = 0;
619
  $optimized_size = 0;
620
  $errors_count = 0;
621
  $optimized_count = 0;
622
+ $thumbnails = [];
623
+
624
  foreach ( $allowed_sizes as $image_size ) {
625
  $url = $this->getImageSizeUrl( $image_size );
626
  $path = $this->getImageSizePath( $image_size );
627
+
628
  if ( ! $url || ! $path ) {
629
  continue;
630
  }
631
+
632
  $original_file_size = 0;
633
+
634
  if ( is_file( $path ) ) {
635
  $original_file_size = filesize( $path );
636
  }
637
+
638
+ $optimized_img_data = $image_processor->process( [
639
  'image_url' => $url,
640
  'image_path' => $path,
641
  'quality' => $image_processor->quality( $quality ),
642
  'save_exif' => $exif,
643
+ ] );
644
  // проверяем на ошибку
645
  if ( is_wp_error( $optimized_img_data ) ) {
646
  $errors_count ++;
655
  if ( ! $optimized_img_data['src_size'] ) {
656
  $optimized_img_data['src_size'] = $original_file_size;
657
  }
658
+
659
  // при отрицательной оптимизации ставим значение оригинала
660
  if ( $optimized_img_data['optimized_size'] > $original_file_size ) {
661
  $optimized_img_data['optimized_size'] = $original_file_size;
662
  }
663
+
664
  $thumbnails[ $image_size ] = $optimized_img_data;
665
+
666
  //просчитываем статистику
667
  $original_size += $optimized_img_data['src_size'];
668
  $optimized_size += $optimized_img_data['optimized_size'];
669
  $optimized_count ++;
670
  }
671
  }
672
+
673
+ return [
674
  'errors_count' => $errors_count,
675
  'original_size' => $original_size,
676
  'optimized_size' => $optimized_size,
677
  'thumbnails_count' => $optimized_count,
678
  'thumbnails' => $thumbnails,
679
+ ];
680
  }
681
+
682
  /**
683
  * Возвращает путь.
684
  *
685
+ * @param string $image_size Размер(thumbnail, medium ... )
686
  *
687
  * @return string
688
  */
689
  public function getPath( $image_size = '' ) {
690
+
691
  if ( empty( $image_size ) ) {
692
  $path = $this->path;
693
  } else {
694
  $path = $this->getImageSizePath( $image_size );
695
  }
696
+
697
  return $path;
698
  }
699
+
700
  /**
701
  * Заменяет оригинальный файл на оптимизированный.
702
  *
703
+ * @param array $optimized_img_data Hезультат оптимизации ввиде массива данных.
704
+ * @param string $image_size Размер (thumbnail, medium ... )
705
  *
706
  * @return bool
707
  */
708
  public function replaceOriginalFile( $optimized_img_data, $image_size = '' ) {
709
+
710
  $optimized_img_url = $optimized_img_data['optimized_img_url'];
711
+
712
  if ( isset( $optimized_img_data['not_need_download'] ) && (bool) $optimized_img_data['not_need_download'] ) {
713
  $optimized_file = $optimized_img_url;
714
  } else {
715
  $optimized_file = $this->remoteDownloadImage( $optimized_img_url );
716
  }
717
+
718
  if ( empty( $optimized_file ) ) {
719
  WRIO_Logger::error( sprintf( 'Unable to replace original image with new as failed to download %s', $optimized_img_url ) );
720
+
721
  return false;
722
  }
723
+
724
  if ( isset( $optimized_img_data['not_need_replace'] ) && $optimized_img_data['not_need_replace'] ) {
725
  // если картинка уже оптимизирована и провайдер её не может уменьшить - он может вернуть положительный ответ, но без самой картинки. В таком случае ничего заменять не надо
726
  return true;
727
  }
728
+
729
  $attachment_size_path = $this->getPath( $image_size );
730
+
731
  if ( ! is_file( $attachment_size_path ) ) {
732
  return false;
733
  }
734
+
735
  $bytes = @file_put_contents( $attachment_size_path, $optimized_file );
736
+
737
  if ( $bytes === false ) {
738
  WRIO_Logger::error( sprintf( 'Failed to put new image\'s %s content to %s as file_put_contents() failed', $optimized_img_url, $attachment_size_path ) );
739
+
740
  return false;
741
  }
742
+
743
  return true;
744
  }
745
+
746
  /**
747
  * Скачивание изображения с удалённого сервера
748
  *
751
  * @return string|null Image content on success, NULL on failure.
752
  */
753
  protected function remoteDownloadImage( $url ) {
754
+
755
  if ( ! function_exists( 'curl_version' ) ) {
756
  $content = @file_get_contents( $url );
757
+
758
  if ( $content === false ) {
759
  WRIO_Logger::error( sprintf( 'Failed to get content of "%s" using file_get_contents()', $url ) );
760
+
761
  return null;
762
  }
763
+
764
  return $content;
765
  }
766
+
767
  $ch = curl_init();
768
  curl_setopt( $ch, CURLOPT_HEADER, 0 );
769
  curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
770
  curl_setopt( $ch, CURLOPT_URL, $url );
771
+
772
  $image_body = curl_exec( $ch );
773
  $http_code = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
774
  if ( $http_code != '200' ) {
775
  $image_body = false;
776
  }
777
  curl_close( $ch );
778
+
779
  if ( $image_body === false ) {
780
  WRIO_Logger::error( sprintf( 'Failed to get content of "%s" using curl_exec()', $url ) );
781
+
782
  return null;
783
  }
784
+
785
  return $image_body;
786
  }
787
+
788
  /**
789
  * Возвращает свойство аттачмента
790
  *
791
+ * @param string $property имя свойства
792
  *
793
  * @return mixed
794
  */
796
  if ( isset( $this->$property ) ) {
797
  return $this->$property;
798
  }
799
+
800
  return false;
801
  }
802
+
803
  /**
804
  * Возвращает URL изображения по указанному размеру
805
  *
806
+ * @param string $size - размер изображения(thumbnail,medium,large...)
807
  *
808
  * @return string|null
809
  */
811
  if ( ! isset( $this->attachment_meta['sizes'][ $size ] ) ) {
812
  return null;
813
  }
814
+
815
  $file = $this->attachment_meta['sizes'][ $size ]['file'];
816
  $url = str_replace( wp_basename( $this->url ), $file, $this->url );
817
+
818
  return $url;
819
  }
820
+
821
  /**
822
  * Возвращает путь к изображению по указанному размеру.
823
  *
824
+ * @param string $size Размер изображения (thumbnail, medium, large ...)
825
  *
826
  * @return string Путь до изображения.
827
  */
829
  if ( ! isset( $this->attachment_meta['sizes'][ $size ] ) ) {
830
  return null;
831
  }
832
+
833
  $file = $this->attachment_meta['sizes'][ $size ]['file'];
834
  $path = str_replace( wp_basename( $this->path ), $file, $this->path );
835
+
836
  return $path;
837
  }
838
+
839
  /**
840
  * Проверка необходимости делать изменение размера.
841
  *
843
  */
844
  protected function isNeedResize() {
845
  $resize_large_images = WRIO_Plugin::app()->getPopulateOption( 'resize_larger', true );
846
+
847
  if ( ! $resize_large_images ) {
848
  return false;
849
  }
850
+
851
  $resize_larger_w = (int) WRIO_Plugin::app()->getPopulateOption( 'resize_larger_w', 1600 );
852
  $resize_larger_h = (int) WRIO_Plugin::app()->getPopulateOption( 'resize_larger_h', 1600 );
853
+
854
  if ( ! $resize_larger_w && ! $resize_larger_h ) {
855
  return false;
856
  }
857
+
858
  // если ширина и высота установлены и > 0
859
  if ( $this->attachment_meta['width'] >= $this->attachment_meta['height'] ) {
860
  $larger_side = $this->attachment_meta['width'];
877
  if ( $larger_side <= $resize_larger_side ) {
878
  return false;
879
  }
880
+
881
  return true;
882
  }
883
+
884
  /**
885
  * Возвращает метаданные аттачмента
886
  *
889
  public function getMetaData() {
890
  return $this->attachment_meta;
891
  }
892
+
893
  /**
894
  * Изменяет размер изображения до заданного в настройках размера.
895
  *
898
  protected function resize() {
899
  $resize_larger_h = (int) WRIO_Plugin::app()->getPopulateOption( 'resize_larger_h', 1600 );
900
  $resize_larger_w = (int) WRIO_Plugin::app()->getPopulateOption( 'resize_larger_w', 1600 );
901
+
902
  $image = wp_get_image_editor( $this->path );
903
+
904
  if ( is_wp_error( $image ) ) {
905
  WRIO_Logger::error( sprintf( 'Failed to get image edit via wp_get_image_editor(), error: "%s"', $image->get_error_message() ) );
906
+
907
  return false;
908
  }
909
+
910
  $current_size = $image->get_size();
911
  $new_width = 0;
912
  $new_height = 0;
913
+
914
  // если обе стороны заданы
915
  if ( $resize_larger_h && $resize_larger_w ) {
916
  // определяем большую сторону и по ней маштабируем
934
  $new_height = round( $current_size['height'] * $new_width / $current_size['width'] );
935
  }
936
  }
937
+
938
  $nl = PHP_EOL;
939
  $log_message = sprintf( "\tResize from: %sx%s to %sx%s", $current_size['width'], $current_size['height'], $new_width, $new_height ) . $nl;
940
  $log_message .= sprintf( "\tLarger resize from %sx%s", $resize_larger_w, $resize_larger_h ) . $nl;
941
  $log_message .= sprintf( "\tAbsolute path: %s", $this->path ) . $nl;
942
+
943
  $resize_result = $image->resize( $new_width, $new_height, false );
944
+
945
  if ( is_wp_error( $resize_result ) ) {
946
  $this->writeLog( sprintf( 'Resize error: %s. Details: %s', $resize_result->get_error_messages(), $log_message ) );
947
+
948
  return false;
949
  }
950
+
951
  $save_result = $image->save( $this->path );
952
+
953
  if ( is_wp_error( $save_result ) ) {
954
  $this->writeLog( sprintf( 'Failed to save resized error in db: %s, Details: %s', $save_result->get_error_messages(), $log_message ) );
955
+
956
  return false;
957
  }
958
+
959
  $this->attachment_meta['width'] = $new_width;
960
  $this->attachment_meta['height'] = $new_height;
961
  $this->attachment_meta['old_width'] = $current_size['width'];
962
  $this->attachment_meta['old_height'] = $current_size['height'];
963
+
964
  wp_update_attachment_metadata( $this->id, $this->attachment_meta );
965
+
966
  return true;
967
  }
968
+
969
  /**
970
  * Делает резервную копию
971
  *
973
  */
974
  protected function backup() {
975
  $backup = WIO_Backup::get_instance();
976
+
977
  return $backup->backupAttachment( $this );
978
  }
979
+
980
  /**
981
  * Восстанавливает файлы из резервной копии
982
  *
984
  */
985
  public function restore() {
986
  $backup = WIO_Backup::get_instance();
987
+
988
  return $backup->restoreAttachment( $this );
989
  }
990
  }
includes/classes/class-rio-image-statistic.php CHANGED
@@ -135,7 +135,7 @@ class WRIO_Image_Statistic {
135
  $optimized_count = 0;
136
  }
137
  // unoptimized count: all - optimized - error
138
- $unoptimized_count = $this->getUnoptimizedCount();
139
  if ( $unoptimized_count < 0 ) {
140
  $unoptimized_count = 0;
141
  }
@@ -147,7 +147,7 @@ class WRIO_Image_Statistic {
147
  $percent_diff_line = 100;
148
  }
149
  if ( $total_images ) {
150
- $optimized_images_percent = round( $optimized_count * 100 / $total_images );
151
  } else {
152
  $optimized_images_percent = 0;
153
  }
@@ -166,9 +166,13 @@ class WRIO_Image_Statistic {
166
  }
167
 
168
  /**
169
- * Кол-во неоптимизированных изображений
 
 
 
 
170
  */
171
- public function getUnoptimizedCount() {
172
  global $wpdb;
173
  $db_table = RIO_Process_Queue::table_name();
174
 
@@ -181,57 +185,112 @@ class WRIO_Image_Statistic {
181
 
182
  $total_images = $wpdb->get_var( $sql_unoptimized );
183
 
184
- return $total_images;
185
  }
186
 
187
  /**
188
  * Возвращает результат последних оптимизаций изображений
189
  *
190
- * @param int $limit лимит
191
  *
192
  * @return array {
193
- * Параметры
194
- * {type} string $id id
195
- * {type} string $file_name Имя файла
196
- * {type} string $url URL
197
- * {type} string $thumbnail_url URL превьюшки
198
- * {type} string $original_size Размер до оптимизации
199
- * {type} string $optimized_size Размер после оптимизации
200
- * {type} string $webp_enabled webP включен
201
- * {type} string $webp_size webP размер
202
- * {type} string $original_saving На сколько процентов изменился главный файл
203
- * {type} string $thumbnails_count Сколько превьюшек оптимизировано
204
- * {type} string $total_saving Процент оптимизации главного файла и превьюшек
205
  * }
206
  */
207
  public function get_last_optimized_images( $limit = 100 ) {
208
  global $wpdb;
209
 
210
- $logs = [];
211
  $db_table = RIO_Process_Queue::table_name();
212
- $sql = $wpdb->prepare( "SELECT t1.*,t2.meta_value as attachment_meta
213
- FROM {$db_table} as t1
214
- LEFT JOIN {$wpdb->prefix}postmeta as t2 ON t1.object_id = t2.post_id
215
- WHERE t2.meta_key = '_wp_attachment_metadata' AND t1.item_type = 'attachment' AND t1.result_status IN (%s, %s)
216
  ORDER BY id DESC
217
  LIMIT %d ;", RIO_Process_Queue::STATUS_SUCCESS, RIO_Process_Queue::STATUS_ERROR, $limit );
218
 
219
- $optimized_images = $wpdb->get_results( $sql );
220
 
221
- if ( empty( $optimized_images ) ) {
222
- return $logs;
 
 
223
  }
224
 
225
- $upload_dir = wp_upload_dir();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
226
 
227
- if ( isset( $upload_dir['error'] ) && $upload_dir['error'] !== false ) {
228
- return $logs;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
229
  }
230
 
231
- foreach ( $optimized_images as $row ) {
232
- $optimization_data = new RIO_Process_Queue( $row );
233
- $attachment_meta = unserialize( $row->attachment_meta );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
234
 
 
 
 
235
  $image_url = trailingslashit( $upload_dir['baseurl'] ) . $attachment_meta['file'];
236
  $thumbnail_url = $image_url;
237
 
@@ -240,58 +299,65 @@ class WRIO_Image_Statistic {
240
  $thumbnail_url = str_replace( $image_basename, $attachment_meta['sizes']['thumbnail']['file'], $image_url );
241
  }
242
 
243
- $item = [
244
- 'id' => $row->id,
245
- 'url' => $image_url,
246
- 'thumbnail_url' => $thumbnail_url,
247
- 'file_name' => wp_basename( $attachment_meta['file'] ),
248
- 'original_size' => size_format( $row->original_size, 2 ),
249
- 'optimized_size' => size_format( $row->final_size, 2 ),
250
- 'type' => 'success',
251
- 'webp_size' => null,
252
- 'original_saving' => 0,
253
- 'thumbnails_count' => 0,
254
- 'total_saving' => 0,
255
- ];
256
 
257
  $main_file = trailingslashit( $upload_dir['basedir'] ) . $attachment_meta['file'];
258
 
259
- /**
260
- * @var RIO_Attachment_Extra_Data $extra_data
261
- */
262
- $extra_data = $optimization_data->get_extra_data();
263
-
264
  if ( ! empty( $extra_data ) ) {
265
  $original_main_size = $extra_data->get_original_main_size();
266
 
267
  if ( $original_main_size && file_exists( $main_file ) ) {
268
- $original_saving = ( $original_main_size - filesize( $main_file ) ) * 100 / $original_main_size;
269
- $item['original_saving'] = round( $original_saving ) . '%';
270
  }
271
 
272
  $webp_size = $extra_data->get_webp_main_size();
273
 
274
  if ( $webp_size ) {
275
- $item['webp_size'] = size_format( $webp_size, 2 );
276
  }
277
 
278
- $item['thumbnails_count'] = $extra_data->get_thumbnails_count();
 
279
 
280
- if ( $row->result_status == RIO_Process_Queue::STATUS_ERROR || ! empty( $error ) ) {
281
- $item['type'] = 'error';
282
- $item['error_msg'] = $extra_data->get_error_msg();
283
- }
 
 
 
 
 
 
 
 
284
  }
285
 
286
- if ( $row->original_size ) {
287
- $total_saving = ( $row->original_size - $row->final_size ) * 100 / $row->original_size;
288
- $item['total_saving'] = round( $total_saving, 2 ) . '%';
 
 
 
 
 
 
289
  }
290
 
291
- $logs[] = $item;
 
 
 
292
  }
293
 
294
- return $logs;
295
  }
296
 
297
  /**
135
  $optimized_count = 0;
136
  }
137
  // unoptimized count: all - optimized - error
138
+ $unoptimized_count = static::get_unoptimized_count();
139
  if ( $unoptimized_count < 0 ) {
140
  $unoptimized_count = 0;
141
  }
147
  $percent_diff_line = 100;
148
  }
149
  if ( $total_images ) {
150
+ $optimized_images_percent = floor( $optimized_count * 100 / $total_images );
151
  } else {
152
  $optimized_images_percent = 0;
153
  }
166
  }
167
 
168
  /**
169
+ * Count of non-optimized images
170
+ *
171
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
172
+ * @since 1.3.6
173
+ * @return int
174
  */
175
+ public static function get_unoptimized_count() {
176
  global $wpdb;
177
  $db_table = RIO_Process_Queue::table_name();
178
 
185
 
186
  $total_images = $wpdb->get_var( $sql_unoptimized );
187
 
188
+ return (int) $total_images;
189
  }
190
 
191
  /**
192
  * Возвращает результат последних оптимизаций изображений
193
  *
194
+ * @param int $limit лимит
195
  *
196
  * @return array {
197
+ * Параметры
198
+ * @type string $id id
199
+ * @type string $file_name Имя файла
200
+ * @type string $url URL
201
+ * @type string $thumbnail_url URL превьюшки
202
+ * @type string $original_size Размер до оптимизации
203
+ * @type string $optimized_size Размер после оптимизации
204
+ * @type string $webp_size webP размер
205
+ * @type string $original_saving На сколько процентов изменился главный файл
206
+ * @type string $thumbnails_count Сколько превьюшек оптимизировано
207
+ * @type string $total_saving Процент оптимизации главного файла и превьюшек
 
208
  * }
209
  */
210
  public function get_last_optimized_images( $limit = 100 ) {
211
  global $wpdb;
212
 
213
+ $items = [];
214
  $db_table = RIO_Process_Queue::table_name();
215
+ $sql = $wpdb->prepare( "SELECT * FROM {$db_table}
216
+ WHERE item_type = 'attachment' AND result_status IN (%s, %s)
 
 
217
  ORDER BY id DESC
218
  LIMIT %d ;", RIO_Process_Queue::STATUS_SUCCESS, RIO_Process_Queue::STATUS_ERROR, $limit );
219
 
220
+ $optimized_images = $wpdb->get_results( $sql, ARRAY_A );
221
 
222
+ if ( ! empty( $optimized_images ) ) {
223
+ foreach ( $optimized_images as $row ) {
224
+ $items[] = $this->format_for_log( new RIO_Process_Queue( $row ) );
225
+ }
226
  }
227
 
228
+ return $items;
229
+ }
230
+
231
+ /**
232
+ * @author Alexander Kovalev <alex.kovalevv@gmail.com>
233
+ * @since 1.3.9
234
+ *
235
+ * @param int $object_id
236
+ */
237
+ public function get_last_optimized_image( $object_id ) {
238
+ global $wpdb;
239
+
240
+ $items = [];
241
+ $db_table = RIO_Process_Queue::table_name();
242
+ $sql = $wpdb->prepare( "SELECT * FROM {$db_table}
243