PluginProbe ʕ •ᴥ•ʔ
Robin Image Optimizer – Unlimited Image Optimization, WebP & AVIF / trunk
Robin Image Optimizer – Unlimited Image Optimization, WebP & AVIF vtrunk
2.0.5 trunk 1.3.7 1.4.0 1.4.1 1.4.2 1.4.6 1.5.0 1.5.3 1.5.6 1.5.8 1.6.5 1.6.6 1.6.9 1.7.0 1.7.4 1.8.1 1.8.2 1.9.0 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4
robin-image-optimizer / libs / addons / includes / classes / class.gallery-nextgen.php
robin-image-optimizer / libs / addons / includes / classes Last commit date
format 3 months ago helpers 5 months ago models 5 months ago webp 3 months ago class.backup.php 5 months ago class.custom-folders.php 5 months ago class.folder-image.php 5 months ago class.folder.php 5 months ago class.folders-list-table.php 5 months ago class.gallery-nextgen.php 5 months ago class.image-nextgen.php 5 months ago class.image-statistic-folders.php 5 months ago class.image-statistic-nextgen.php 5 months ago class.wpcli-optimize.php 5 months ago index.php 5 months ago
class.gallery-nextgen.php
616 lines
1 <?php
2
3 // Exit if accessed directly
4 if ( ! defined( 'ABSPATH' ) ) {
5 exit;
6 }
7
8 /**
9 * Класс для работы с галереей nextgen
10 *
11 * @version 1.0
12 */
13 class WRIO_Nextgen_Gallery {
14
15 /**
16 * The single instance of the class.
17 *
18 * @since 1.3.0
19 * @access protected
20 * @var object
21 */
22 protected static $_instance;
23
24 /**
25 * @var array $nextgen_images контейнер для �
26 ранения nextgen_images
27 */
28 private $nextgen_images = [];
29
30 /**
31 * Инициализация функционала nextgen галереи. Установка �
32 уков
33 */
34 public function __construct() {
35 if ( ! wrio_is_active_nextgen_gallery() ) {
36 return;
37 }
38
39 require_once WRIOP_PLUGIN_DIR . '/includes/classes/models/class.nextgen-extra-data.php';
40 require_once WRIOP_PLUGIN_DIR . '/includes/classes/class.image-nextgen.php';
41 require_once WRIOP_PLUGIN_DIR . '/admin/ajax/optimization.php';
42
43 add_filter( 'ngg_manage_images_number_of_columns', [ $this, 'addColumns' ] );
44
45 add_action( 'wp_ajax_wio_ng_reoptimize_image', 'wbcr_riop_reoptimizeImage' );
46 add_action( 'wp_ajax_wio_ng_restore_image', 'wbcr_riop_restoreImage' );
47 add_action( 'wp_ajax_wio_process_ng_images', 'wbcr_riop_optimizeImages' );
48
49 add_action( 'admin_enqueue_scripts', [ $this, 'enqueueMeadiaScripts' ], 10 );
50 add_action( 'ngg_delete_picture', [ $this, 'deleteImageHook' ], 10, 2 );
51 add_action( 'ngg_recovered_image', [ $this, 'recoverImageHook' ], 10, 1 );
52
53 add_filter(
54 'wbcr/rio/optimize_template/reoptimize_ajax_action',
55 [
56 $this,
57 'reoptimizeAjaxAction',
58 ],
59 10,
60 2
61 );
62
63 add_filter( 'wbcr/rio/optimize_template/restore_ajax_action', [ $this, 'restoreAjaxAction' ], 10, 2 );
64 // add_filter( 'wbcr/rio/multisite_blogs', [ $this, 'multisiteBlogs' ], 10, 2 );
65 add_action( 'wbcr/rio/optimize_template/optimized_percent', [ $this, 'optimizedPercent' ], 10, 2 );
66 add_action( 'wbcr/riop/queue_item_saved', [ $this, 'webpSuccess' ], 10, 1 );
67 }
68
69 /**
70 * @return object|\WRIO_Nextgen_Gallery object Main instance.
71 * @since 1.3.0
72 */
73 public static function get_instance() {
74 if ( ! isset( static::$_instance ) ) {
75 static::$_instance = new static();
76 }
77
78 return static::$_instance;
79 }
80
81 /**
82 * Возвращает сайты, на которы�
83 установлен NextGen gallery
84 * Используется в мультисайт режиме
85 *
86 * @param array $blogs сайты
87 * @param string $type тип
88 *
89 * @return array сайты, на которы�
90 установлен nextgen
91 */
92 /*
93 public function multisiteBlogs( $blogs, $type ) {
94 if ( 'nextgen' == $type ) {
95 $nextgen_basename = 'nextgen-gallery/nggallery.php';
96 if ( is_plugin_active_for_network( $nextgen_basename ) ) {
97 return $blogs;
98 } else {
99 $nextgen_blogs = [];
100 foreach ( $blogs as $blog ) {
101 switch_to_blog( intval( $blog->blog_id ) );
102 if ( is_plugin_active( $nextgen_basename ) ) {
103 $nextgen_blogs[] = $blog;
104 }
105 restore_current_blog();
106 }
107
108 return $nextgen_blogs;
109 }
110 }
111
112 return $blogs;
113 }*/
114
115 /**
116 * Хук возвращает ajax action для кнопки переоптимизации
117 */
118 public function reoptimizeAjaxAction( $action, $type ) {
119 if ( $type == 'nextgen' ) {
120 return 'wio_ng_reoptimize_image';
121 }
122
123 return $action;
124 }
125
126 /**
127 * Хук возвращает ajax action для кнопки восстановления
128 */
129 public function restoreAjaxAction( $action, $type ) {
130 if ( $type == 'nextgen' ) {
131 return 'wio_ng_restore_image';
132 }
133
134 return $action;
135 }
136
137 /**
138 * Добавляем стили и скрипты в медиабиблиотеку
139 */
140 public function enqueueMeadiaScripts( $hook ) {
141 if ( strpos( $hook, 'page_nggallery-manage-gallery' ) === false ) {
142 return;
143 }
144 wp_enqueue_style( 'wio-install-addons', WRIO_PLUGIN_URL . '/admin/assets/css/media.css', [], WRIO_Plugin::app()->getPluginVersion() );
145 wp_enqueue_script( 'wio-install-addons', WRIO_PLUGIN_URL . '/admin/assets/js/single-optimization.js', [ 'jquery' ], WRIO_Plugin::app()->getPluginVersion() );
146 }
147
148 /**
149 * Добавляет колонку оптимизации в галерею nextgen
150 */
151 public function addColumns( $count ) {
152 ++$count;
153 add_filter( 'ngg_manage_images_column_' . $count . '_header', [ $this, 'columnTitle' ] );
154 add_filter( 'ngg_manage_images_column_' . $count . '_content', [ $this, 'columnContent' ], 10, 2 );
155
156 return $count;
157 }
158
159 /**
160 * Название колонки оптимизации в галерее
161 */
162 public function columnTitle() {
163 return __( 'Image optimizer', 'robin-image-optimizer' );
164 }
165
166 /**
167 * Возвращает содержимое блока оптимизации
168 */
169 public function columnContent( $output, $image ) {
170 $output = $this->getMediaColumnContent( $image->pid );
171
172 return $output;
173 }
174
175 /**
176 * Возвращает блок оптимизации
177 */
178 public function getMediaColumnContent( $image_id ) {
179
180 $media_library = WRIO_Media_Library::get_instance();
181 $params = $this->calculateParams( $image_id );
182
183 return $media_library->getMediaColumnTemplate( $params, 'nextgen' );
184 }
185
186 /**
187 * Просчитывает параметры блока оптимизации
188 *
189 * @param int $image_id номер изображения nextgen
190 *
191 * @return array $params
192 */
193 public function calculateParams( $image_id ) {
194 $nextgen_image = new WRIO_Image_Nextgen( $image_id );
195 $isOptimized = $nextgen_image->isOptimized();
196 $diff_percent = 0;
197 $diff_percent_all = 0;
198 $original_main_size = 0;
199 $attachment_file_size = 0;
200 $optimized_size = 0;
201 $original_size = 0;
202 $optimization_level = '';
203 $error_msg = '';
204 $backuped = '';
205 if ( $isOptimized ) {
206 $optimization_data = $nextgen_image->getOptimizationData();
207 /**
208 * @var WRIO_Nextgen_Extra_Data $extra_data
209 */
210 $extra_data = $optimization_data->get_extra_data();
211 $optimization_level = $optimization_data->get_processing_level();
212 $original_main_size = $extra_data->get_original_main_size();
213 $attachment_file_size = $optimization_data->get_final_size();
214 $optimized_size = $optimization_data->get_final_size();
215 $original_size = $optimization_data->get_original_size();
216 $backuped = $optimization_data->get_is_backed_up();
217 $error_msg = $extra_data->get_error_msg();
218 if ( $attachment_file_size and $original_main_size ) {
219 $diff_percent = round( ( $original_main_size - $attachment_file_size ) * 100 / $original_main_size );
220 }
221 if ( $optimized_size and $original_size ) {
222 $diff_percent_all = round( ( $original_size - $optimized_size ) * 100 / $original_size );
223 }
224 }
225 $params = [
226 'attachment_id' => $image_id,
227 'is_optimized' => $isOptimized,
228 'attach_dimensions' => 0,
229 'attachment_file_size' => $attachment_file_size,
230 'optimized_size' => $optimized_size,
231 'original_size' => $original_size,
232 'original_main_size' => $original_main_size,
233 'thumbnails_optimized' => 1,
234 'optimization_level' => $optimization_level,
235 'error_msg' => $error_msg,
236 'backuped' => $backuped,
237 'diff_percent' => $diff_percent,
238 'diff_percent_all' => $diff_percent_all,
239 'is_skipped' => false,
240 ];
241
242 return $params;
243 }
244
245 /**
246 * Возвращает объект nextgen_image
247 *
248 * @param int $image_id
249 * @param array $image_meta
250 *
251 * @return WRIO_Image_Nextgen
252 */
253 public function getNextgenImage( $image_id, $image_meta = false ) {
254 if ( ! isset( $this->nextgen_images[ $image_id ] ) ) {
255 $this->nextgen_images[ $image_id ] = new WRIO_Image_Nextgen( $image_id, $image_meta );
256 }
257
258 return $this->nextgen_images[ $image_id ];
259 }
260
261 /**
262 * Оптимизирует nextgen_image
263 *
264 * @param int $image_id номер картинки в таблице nextgen
265 * @param string $level качество
266 *
267 * @return array
268 */
269 public function optimizeNextgenImage( $image_id, $level = '' ) {
270 $nextgen_image = $this->getNextgenImage( $image_id );
271 $optimization_data = $nextgen_image->getOptimizationData();
272 if ( 'processing' == $optimization_data->get_result_status() ) {
273 return $this->deferredOptimizeNextgenImage( $image_id );
274 }
275 $image_statistics = WRIO_Image_Statistic_Nextgen::get_instance();
276 if ( $nextgen_image->isOptimized() ) {
277 $optimized_size = $optimization_data->get_final_size();
278 $original_size = $optimization_data->get_original_size();
279 $webp_optimized_size = $optimization_data->get_extra_data()->get_webp_main_size();
280 $image_statistics->deductFromField( 'webp_optimized_size', $webp_optimized_size );
281 $image_statistics->deductFromField( 'optimized_size', $optimized_size );
282 $image_statistics->deductFromField( 'original_size', $original_size );
283 $nextgen_image->restore();
284 }
285 $image_optimized_data = $nextgen_image->optimize( $level );
286 $original_size = $image_optimized_data['original_size'];
287 $optimized_size = $image_optimized_data['optimized_size'];
288 $image_statistics->addToField( 'optimized_size', $optimized_size );
289 $image_statistics->addToField( 'original_size', $original_size );
290 $image_statistics->save();
291
292 return $image_optimized_data;
293 }
294
295 /**
296 * Отложенная оптимизация nextgen_image.
297 *
298 * @param int $image_id
299 *
300 * @return array|bool array on success, false on failure.
301 */
302 protected function deferredOptimizeNextgenImage( $image_id ) {
303 $nextgen_image = $this->getNextgenImage( $image_id );
304 $optimization_data = $nextgen_image->getOptimizationData();
305 $image_processor = WIO_OptimizationTools::getImageProcessor();
306
307 // если текущий сервер оптимизации не поддерживает отложенную оптимизацию, а в очереди есть аттачменты - ставим им ошибку
308 if ( ! $image_processor->isDeferred() ) {
309 $optimization_data->set_result_status( 'error' );
310
311 /**
312 * @var WRIO_Nextgen_Extra_Data $extra_data
313 */
314 $extra_data = $optimization_data->get_extra_data();
315 $extra_data->set_error( 'deferred' );
316 $extra_data->set_error_msg( 'server not support deferred optimization' );
317 $optimization_data->set_extra_data( $extra_data );
318 $optimization_data->save();
319
320 WRIO_Plugin::app()->logger->error( sprintf( 'Server %s does not support deferred optimization', get_class( $image_processor ) ) );
321
322 return false;
323 }
324 $optimized_data = $nextgen_image->deferredOptimization();
325 if ( $optimized_data ) {
326 $image_statistics = WRIO_Image_Statistic_Nextgen::get_instance();
327 $image_statistics->addToField( 'optimized_size', $optimized_data['optimized_size'] );
328 $image_statistics->addToField( 'original_size', $optimized_data['original_size'] );
329 $image_statistics->save();
330 }
331
332 return $optimized_data;
333 }
334
335
336 /**
337 * Обработка не оптимизированны�
338 изображений
339 *
340 * @param int $max_process_per_request кол-во аттачментов за 1 запуск
341 *
342 * @return array|\WP_Error
343 */
344 public function processUnoptimizedImages( $max_process_per_request = 5 ) {
345 $backup = WRIOP_Backup::get_instance();
346 $backup_origin_images = WRIO_Plugin::app()->getPopulateOption( 'backup_origin_images', false );
347 if ( $backup_origin_images and ! $backup->isBackupWritable() ) {
348 return new WP_Error( 'unwritable_backup_dir', __( 'No access for writing backups.', 'robin-image-optimizer' ) );
349 }
350 if ( ! $backup->isUploadWritable() ) {
351 return new WP_Error( 'unwritable_upload_dir', __( 'No access for writing backups.', 'robin-image-optimizer' ) );
352 }
353 $image_statistics = WRIO_Image_Statistic_Nextgen::get_instance();
354
355 // выборка неоптимизированны�
356 изображений
357 $gallery_images = $image_statistics->getUnoptimized( $max_process_per_request ); // тут будет выборка
358 $total_unoptimized = $image_statistics->getUnoptimizedCount(); // тут общее кол-во неоптимизированны�
359
360 $gallery_images_count = 0;
361 if ( isset( $gallery_images ) ) {
362 $gallery_images_count = count( $gallery_images );
363 }
364
365 $optimized_count = 0;
366
367 // обработка
368 if ( $gallery_images_count ) {
369 foreach ( $gallery_images as $gallery_image ) {
370 $this->optimizeNextgenImage( $gallery_image->pid );
371 }
372 }
373
374 $remain = $total_unoptimized - $gallery_images_count;
375 // проверяем, есть ли аттачменты в очереди на отложенную оптимизацию
376 $optimized_data = $this->processDeferredOptimization();
377 if ( $optimized_data ) {
378 $optimized_count = $optimized_data['optimized_count'];
379 $remain = $total_unoptimized - $optimized_count;
380 }
381 if ( $remain <= 0 ) {
382 $remain = 0;
383 }
384 $responce = [
385 'remain' => $remain,
386 'end' => false,
387 'last_optimized' => $image_statistics->get_last_optimized_images( $max_process_per_request ),
388 'statistic' => $image_statistics->load(),
389 'optimized_count' => $optimized_count,
390 ];
391
392 return $responce;
393 }
394
395 /**
396 * Отложенная оптимизация
397 *
398 * @return bool|array
399 */
400 protected function processDeferredOptimization() {
401 global $wpdb;
402 $db_table = RIO_Process_Queue::table_name();
403 $image_id = $wpdb->get_var( "SELECT object_id FROM {$db_table} WHERE item_type = 'nextgen' and result_status = 'processing' LIMIT 1;" );
404 if ( ! $image_id ) {
405 return false;
406 }
407 $nextgen_image = $this->getNextgenImage( $image_id );
408 $optimized_data = $nextgen_image->deferredOptimization();
409 if ( $optimized_data ) {
410 $image_statistics = WRIO_Image_Statistic_Nextgen::get_instance();
411 $image_statistics->addToField( 'optimized_size', $optimized_data['optimized_size'] );
412 $image_statistics->addToField( 'original_size', $optimized_data['original_size'] );
413 $image_statistics->save();
414
415 return $optimized_data;
416 }
417
418 return false;
419 }
420
421 /**
422 * Сбрасывает текущие ошибки оптимизации
423 * Позволяет изображениям, которые оптимизированы с ошибкой, заново пройти оптимизацию.
424 *
425 * @return void
426 */
427 public function resetCurrentErrors() {
428 // do_action( 'wbcr/rio/multisite_current_blog' );
429
430 global $wpdb;
431
432 $db_table = RIO_Process_Queue::table_name();
433
434 $wpdb->delete(
435 $db_table,
436 [
437 'item_type' => 'nextgen',
438 'result_status' => 'error',
439 ],
440 [ '%s', '%s' ]
441 );
442 // do_action( 'wbcr/rio/multisite_restore_blog' );
443 }
444
445 /**
446 * Хук срабатывает при восстановлении картинок через стандартный интерфейс nextgen
447 */
448 public function recoverImageHook( $image ) {
449 $image_id = isset( $image->pid ) ? $image->pid : 0;
450 $nextgen_image = new WRIO_Image_Nextgen( $image_id );
451 if ( $nextgen_image->isOptimized() ) {
452 $optimization_data = $nextgen_image->getOptimizationData();
453 $image_statistics = WRIO_Image_Statistic_Nextgen::get_instance();
454 $optimized_size = $optimization_data->get_final_size();
455 $original_size = $optimization_data->get_original_size();
456 $webp_optimized_size = $optimization_data->get_extra_data()->get_webp_main_size();
457 $image_statistics->deductFromField( 'webp_optimized_size', $webp_optimized_size );
458 $image_statistics->deductFromField( 'optimized_size', $optimized_size );
459 $image_statistics->deductFromField( 'original_size', $original_size );
460 $image_statistics->save();
461
462 if ( ! $nextgen_image->restore() ) {
463 WRIO_Plugin::app()->logger->error( sprintf( 'Failed to restore Nextgen image. Object info: %s', wp_json_encode( $nextgen_image ) ) );
464 }
465
466 $optimization_data->delete();
467 }
468 $this->deleteNextgenOptimizationData( $image_id );
469 }
470
471 /**
472 * Хук срабатывает при удалении картинки
473 */
474 public function deleteImageHook( $image_id, $image ) {
475 $nextgen_image = new WRIO_Image_Nextgen( $image_id );
476
477 if ( $nextgen_image->isOptimized() ) {
478 $restored = $nextgen_image->restore();
479
480 if ( ! is_wp_error( $restored ) ) {
481 $optimization_data = $nextgen_image->getOptimizationData();
482 $image_statistics = WRIO_Image_Statistic_Nextgen::get_instance();
483 $optimized_size = $optimization_data->get_final_size();
484 $original_size = $optimization_data->get_original_size();
485 $webp_optimized_size = $optimization_data->get_extra_data()->get_webp_main_size();
486 $image_statistics->deductFromField( 'webp_optimized_size', $webp_optimized_size );
487 $image_statistics->deductFromField( 'optimized_size', $optimized_size );
488 $image_statistics->deductFromField( 'original_size', $original_size );
489 $image_statistics->save();
490
491 WRIO_Plugin::app()->logger->error( sprintf( 'Failed to restore Nextgen image. Object info: %s', wp_json_encode( $nextgen_image ) ) );
492
493 $optimization_data->delete();
494 }
495 }
496 $this->deleteNextgenOptimizationData( $image_id );
497 }
498
499 /**
500 * Удаляет данные по оптимизации из таблицы в базе данны�
501
502 *
503 * @param int $image_id
504 *
505 * @return void
506 */
507 protected function deleteNextgenOptimizationData( $image_id = 0 ) {
508 global $wpdb;
509
510 $db_table = RIO_Process_Queue::table_name();
511
512 $wpdb->delete(
513 $db_table,
514 [
515 'object_id' => $image_id,
516 'item_type' => 'nextgen',
517 ]
518 );
519 }
520
521 /**
522 * Возвращает процент оптимизации
523 * Фильтр wbcr/rio/optimize_template/optimized_percent
524 *
525 * @param int $percent процент оптимизации
526 * @param string $type тип страницы
527 *
528 * @return int процент оптимизации
529 */
530 public function optimizedPercent( $percent, $type ) {
531 if ( 'nextgen' == $type ) {
532 $image_statistics = WRIO_Image_Statistic_Nextgen::get_instance();
533
534 return $image_statistics->getOptimizedPercent();
535 }
536
537 return $percent;
538 }
539
540 /**
541 * Со�
542 раняет WebP размер
543 *
544 * @param RIO_Process_Queue $queue_model
545 *
546 * @return bool
547 */
548 public function webpSuccess( $queue_model ) {
549 if ( ! class_exists( 'WRIO\WEBP\Listener' ) ) {
550 return false; // если не установлена премиум версия, то WebP не активен
551 }
552 if ( $queue_model->get_item_type() !== WRIO\WEBP\Listener::DEFAULT_TYPE ) {
553 return false;
554 }
555 if ( $queue_model->get_result_status() !== RIO_Process_Queue::STATUS_SUCCESS ) {
556 return false;
557 }
558
559 /**
560 * @var RIOP_WebP_Extra_Data $extra_data
561 */
562 $extra_data = $queue_model->get_extra_data();
563 $item_type = $extra_data->get_convert_from();
564
565 if ( $item_type != 'nextgen' ) {
566 return false;
567 }
568
569 if ( ! $queue_model->object_id ) {
570 return false;
571 }
572
573 $optimization_data = new RIO_Process_Queue(
574 [
575 'object_id' => $queue_model->object_id,
576 'item_type' => 'nextgen',
577 ]
578 );
579
580 $optimization_data->load();
581
582 /**
583 * @var WRIO_Nextgen_Extra_Data $extra_data
584 */
585 $extra_data = $optimization_data->get_extra_data();
586 if ( ! $extra_data ) {
587 return false;
588 }
589
590 $extra_data->set_webp_main_size( $queue_model->get_final_size() );
591 $optimization_data->set_extra_data( $extra_data );
592 add_filter( 'wbcr/riop/queue_item_save_execute_hook', '__return_false' );
593 $optimization_data->save();
594 remove_filter( 'wbcr/riop/queue_item_save_execute_hook', '__return_false' );
595
596 return true;
597 }
598
599 /**
600 * Get ID's of unoptimized attachments
601 *
602 * @return array
603 */
604 public function getUnoptimizedImages() {
605 $image_statistics = WRIO_Image_Statistic_Nextgen::get_instance();
606 $gallery_images = $image_statistics->getUnoptimized( PHP_INT_MAX ); // тут будет выборка
607
608 $return = [];
609 foreach ( $gallery_images as $gallery_image ) {
610 $return[] = $gallery_image->pid;
611 }
612
613 return $return;
614 }
615 }
616