PluginProbe
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF / 2.2.2
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF v2.2.2
2.3.4 2.3.3 2.3.2 2.3.1 2.3.0 2.2.9 2.2.8 trunk 1.10 1.3.3 1.3.4 1.3.5 1.3.5.1 1.3.5.2 1.3.6 1.3.6.1 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.5 All 103 releases
imagify / inc / classes / class-imagify-views.php

class-imagify-views.php in Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF 2.2.2, at inc/classes/class-imagify-views.php

685 lines 18.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 use Imagify\User\User;
4
5 defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
6
7 /**
8 * Class that handles templates and menus.
9 *
10 * @since 1.7
11 */
12 class Imagify_Views {
13
14 /**
15 * Class version.
16 *
17 * @var string
18 * @since 1.7
19 */
20 const VERSION = '1.1';
21
22 /**
23 * Slug used for the settings page URL.
24 *
25 * @var string
26 * @since 1.7
27 */
28 protected $slug_settings;
29
30 /**
31 * Slug used for the bulk optimization page URL.
32 *
33 * @var string
34 * @since 1.7
35 */
36 protected $slug_bulk;
37
38 /**
39 * Slug used for the "custom folders" page URL.
40 *
41 * @var string
42 * @since 1.7
43 */
44 protected $slug_files;
45
46 /**
47 * A list of JS templates to print at the end of the page.
48 *
49 * @var array
50 * @since 1.9
51 */
52 protected $templates_in_footer = [];
53
54 /**
55 * Stores the "custom folders" files list instance.
56 *
57 * @var Imagify_Files_List_Table
58 * @since 1.7
59 */
60 protected $list_table;
61
62 /**
63 * Filesystem object.
64 *
65 * @var Imagify_Filesystem
66 * @since 1.7.1
67 */
68 protected $filesystem;
69
70 /**
71 * The single instance of the class.
72 *
73 * @var object
74 * @since 1.7
75 */
76 protected static $_instance;
77
78
79 /** ----------------------------------------------------------------------------------------- */
80 /** INSTANCE/INIT =========================================================================== */
81 /** ----------------------------------------------------------------------------------------- */
82
83 /**
84 * The constructor.
85 *
86 * @since 1.7
87 */
88 protected function __construct() {
89 $this->slug_settings = IMAGIFY_SLUG;
90 $this->slug_bulk = IMAGIFY_SLUG . '-bulk-optimization';
91 $this->slug_files = IMAGIFY_SLUG . '-files';
92 $this->filesystem = Imagify_Filesystem::get_instance();
93 }
94
95 /**
96 * Get the main Instance.
97 *
98 * @since 1.7
99 *
100 * @return object Main instance.
101 */
102 public static function get_instance() {
103 if ( ! isset( self::$_instance ) ) {
104 self::$_instance = new self();
105 }
106
107 return self::$_instance;
108 }
109
110 /**
111 * Launch the hooks.
112 *
113 * @since 1.7
114 */
115 public function init() {
116 // Menu items.
117 add_action( 'admin_menu', [ $this, 'add_site_menus' ] );
118
119 if ( imagify_is_active_for_network() ) {
120 add_action( 'network_admin_menu', [ $this, 'add_network_menus' ] );
121 }
122
123 // Action links in plugins list.
124 $basename = plugin_basename( IMAGIFY_FILE );
125 add_filter( 'plugin_action_links_' . $basename, [ $this, 'plugin_action_links' ] );
126 add_filter( 'network_admin_plugin_action_links_' . $basename, [ $this, 'plugin_action_links' ] );
127
128 // Save the "per page" option value from the files list screen.
129 add_filter( 'set-screen-option', [ 'Imagify_Files_List_Table', 'save_screen_options' ], 10, 3 );
130
131 // JS templates in footer.
132 add_action( 'admin_print_footer_scripts', [ $this, 'print_js_templates' ] );
133 }
134
135
136 /** ----------------------------------------------------------------------------------------- */
137 /** MENU ITEMS ============================================================================== */
138 /** ----------------------------------------------------------------------------------------- */
139
140 /**
141 * Add sub-menus for all sites.
142 *
143 * @since 1.7
144 */
145 public function add_site_menus() {
146 $wp_context = imagify_get_context( 'wp' );
147
148 // Sub-menu item: bulk optimization.
149 add_media_page( __( 'Bulk Optimization', 'imagify' ), __( 'Bulk Optimization', 'imagify' ), $wp_context->get_capacity( 'bulk-optimize' ), $this->get_bulk_page_slug(), [ $this, 'display_bulk_page' ] );
150
151 if ( imagify_is_active_for_network() ) {
152 return;
153 }
154
155 /**
156 * Plugin is not network activated.
157 */
158 if ( imagify_can_optimize_custom_folders() ) {
159 // Sub-menu item: custom folders list.
160 $cf_context = imagify_get_context( 'custom-folders' );
161 $screen_id = add_media_page( __( 'Other Media optimized by Imagify', 'imagify' ), __( 'Other Media', 'imagify' ), $cf_context->get_capacity( 'optimize' ), $this->get_files_page_slug(), [ $this, 'display_files_list' ] );
162
163 if ( $screen_id ) {
164 // Load the data for this page.
165 add_action( 'load-' . $screen_id, [ $this, 'load_files_list' ] );
166 }
167 }
168
169 // Sub-menu item: settings.
170 add_options_page( 'Imagify', 'Imagify', $wp_context->get_capacity( 'manage' ), $this->get_settings_page_slug(), [ $this, 'display_settings_page' ] );
171 }
172
173 /**
174 * Add menu and sub-menus in the network admin when Imagify is network-activated.
175 *
176 * @since 1.7
177 */
178 public function add_network_menus() {
179 global $submenu;
180
181 $wp_context = imagify_get_context( 'wp' );
182
183 if ( ! imagify_can_optimize_custom_folders() ) {
184 // Main item: settings (edge case).
185 add_menu_page( 'Imagify', 'Imagify', $wp_context->get_capacity( 'manage' ), $this->get_settings_page_slug(), array( $this, 'display_settings_page' ) );
186 return;
187 }
188
189 $cf_context = imagify_get_context( 'custom-folders' );
190
191 // Main item: bulk optimization (custom folders).
192 add_menu_page( __( 'Bulk Optimization', 'imagify' ), 'Imagify', $cf_context->current_user_can( 'bulk-optimize' ), $this->get_bulk_page_slug(), array( $this, 'display_bulk_page' ) );
193
194 // Sub-menu item: custom folders list.
195 $screen_id = add_submenu_page( $this->get_bulk_page_slug(), __( 'Other Media optimized by Imagify', 'imagify' ), __( 'Other Media', 'imagify' ), $cf_context->current_user_can( 'bulk-optimize' ), $this->get_files_page_slug(), array( $this, 'display_files_list' ) );
196
197 // Sub-menu item: settings.
198 add_submenu_page( $this->get_bulk_page_slug(), 'Imagify', __( 'Settings', 'imagify' ), $wp_context->get_capacity( 'manage' ), $this->get_settings_page_slug(), array( $this, 'display_settings_page' ) );
199
200 // Change the sub-menu label.
201 if ( ! empty( $submenu[ $this->get_bulk_page_slug() ] ) ) {
202 $submenu[ $this->get_bulk_page_slug() ][0][0] = __( 'Bulk Optimization', 'imagify' ); // WPCS: override ok.
203 }
204
205 if ( $screen_id ) {
206 // On the "Other Media optimized by Imagify" page, load the data.
207 add_action( 'load-' . $screen_id, array( $this, 'load_files_list' ) );
208 }
209 }
210
211
212 /** ----------------------------------------------------------------------------------------- */
213 /** PLUGIN ACTION LINKS ===================================================================== */
214 /** ----------------------------------------------------------------------------------------- */
215
216 /**
217 * Add links to the plugin row in the plugins list.
218 *
219 * @since 1.7
220 *
221 * @param array $actions An array of action links.
222 * @return array
223 */
224 public function plugin_action_links( $actions ) {
225 array_unshift( $actions, sprintf( '<a href="%s" target="_blank">%s</a>', esc_url( imagify_get_external_url( 'documentation' ) ), __( 'Documentation', 'imagify' ) ) );
226 array_unshift( $actions, sprintf( '<a href="%s">%s</a>', esc_url( get_imagify_admin_url( 'bulk-optimization' ) ), __( 'Bulk Optimization', 'imagify' ) ) );
227 array_unshift( $actions, sprintf( '<a href="%s">%s</a>', esc_url( get_imagify_admin_url() ), __( 'Settings', 'imagify' ) ) );
228 return $actions;
229 }
230
231
232 /** ----------------------------------------------------------------------------------------- */
233 /** MAIN PAGE TEMPLATES ===================================================================== */
234 /** ----------------------------------------------------------------------------------------- */
235
236 /**
237 * The main settings page.
238 *
239 * @since 1.7
240 */
241 public function display_settings_page() {
242 $this->print_template( 'page-settings' );
243 }
244
245 /**
246 * The bulk optimization page.
247 *
248 * @since 1.7
249 */
250 public function display_bulk_page() {
251 $types = array();
252 $data = array(
253 // Limits.
254 'unoptimized_attachment_limit' => 0,
255 // What to optimize.
256 'icon' => 'images-alt2',
257 'title' => __( 'Optimize your media files', 'imagify' ),
258 'groups' => array(),
259 );
260
261 if ( imagify_is_screen( 'bulk' ) ) {
262 if ( ! is_network_admin() ) {
263 /**
264 * Library: in each site.
265 */
266 $types['library|wp'] = 1;
267 }
268
269 if ( imagify_can_optimize_custom_folders() && ( imagify_is_active_for_network() && is_network_admin() || ! imagify_is_active_for_network() ) ) {
270 /**
271 * Custom folders: in network admin only if network activated, in each site otherwise.
272 */
273 $types['custom-folders|custom-folders'] = 1;
274 }
275 }
276
277 /**
278 * Filter the types to display in the bulk optimization page.
279 *
280 * @since 1.7.1
281 * @author Grégory Viguier
282 *
283 * @param array $types The folder types displayed on the page. If a folder type is "library", the context should be suffixed after a pipe character. They are passed as array keys.
284 */
285 $types = apply_filters( 'imagify_bulk_page_types', $types );
286 $types = array_filter( (array) $types );
287
288 if ( isset( $types['library|wp'] ) ) {
289 // Limits.
290 $data['unoptimized_attachment_limit'] += imagify_get_unoptimized_attachment_limit();
291 // Group.
292 $data['groups']['library'] = array(
293 /**
294 * The group_id corresponds to the file names like 'part-bulk-optimization-results-row-{$group_id}'.
295 * It is also used in get_imagify_localize_script_translations().
296 */
297 'group_id' => 'library',
298 'context' => 'wp',
299 'title' => __( 'Media Library', 'imagify' ),
300 /* translators: 1 is the opening of a link, 2 is the closing of this link. */
301 'footer' => sprintf( __( 'You can also re-optimize your media files from your %1$sMedia Library%2$s screen.', 'imagify' ), '<a href="' . esc_url( admin_url( 'upload.php' ) ) . '">', '</a>' ),
302 );
303 }
304
305 if ( isset( $types['custom-folders|custom-folders'] ) ) {
306 if ( ! Imagify_Folders_DB::get_instance()->has_items() ) {
307 // New Feature!
308 $data['no-custom-folders'] = true;
309 } elseif ( Imagify_Folders_DB::get_instance()->has_active_folders() ) {
310 // Group.
311 $data['groups']['custom-folders'] = array(
312 'group_id' => 'custom-folders',
313 'context' => 'custom-folders',
314 'title' => __( 'Custom folders', 'imagify' ),
315 /* translators: 1 is the opening of a link, 2 is the closing of this link. */
316 'footer' => sprintf( __( 'You can re-optimize your media files more finely directly in the %1$smedia management%2$s.', 'imagify' ), '<a href="' . esc_url( get_imagify_admin_url( 'files-list' ) ) . '">', '</a>' ),
317 );
318 }
319 }
320
321 // Add generic stats.
322 $data = array_merge( $data, imagify_get_bulk_stats( $types, array(
323 'fullset' => true,
324 ) ) );
325
326 /**
327 * Filter the data to use on the bulk optimization page.
328 *
329 * @since 1.7
330 * @since 1.7.1 Added the $types parameter.
331 * @author Grégory Viguier
332 *
333 * @param array $data The data to use.
334 * @param array $types The folder types displayed on the page. They are passed as array keys.
335 */
336 $data = apply_filters( 'imagify_bulk_page_data', $data, $types );
337
338 $this->print_template( 'page-bulk', $data );
339 }
340
341 /**
342 * The page displaying the "custom folders" files.
343 *
344 * @since 1.7
345 */
346 public function display_files_list() {
347 $this->print_template( 'page-files-list' );
348 }
349
350 /**
351 * Initiate the "custom folders" list table data.
352 *
353 * @since 1.7
354 */
355 public function load_files_list() {
356 // Instantiate the list.
357 $this->list_table = new Imagify_Files_List_Table( array(
358 'screen' => 'imagify-files',
359 ) );
360
361 // Query the Items.
362 $this->list_table->prepare_items();
363 }
364
365
366 /** ----------------------------------------------------------------------------------------- */
367 /** GETTERS ================================================================================= */
368 /** ----------------------------------------------------------------------------------------- */
369
370 /**
371 * Get the settings page slug.
372 *
373 * @since 1.7
374 *
375 * @return string
376 */
377 public function get_settings_page_slug() {
378 return $this->slug_settings;
379 }
380
381 /**
382 * Get the bulk optimization page slug.
383 *
384 * @since 1.7
385 *
386 * @return string
387 */
388 public function get_bulk_page_slug() {
389 return $this->slug_bulk;
390 }
391
392 /**
393 * Get the "custom folders" files page slug.
394 *
395 * @since 1.7
396 *
397 * @return string
398 */
399 public function get_files_page_slug() {
400 return $this->slug_files;
401 }
402
403
404 /** ----------------------------------------------------------------------------------------- */
405 /** PAGE TESTS ============================================================================== */
406 /** ----------------------------------------------------------------------------------------- */
407
408 /**
409 * Tell if we’re displaying the settings page.
410 *
411 * @since 1.9
412 *
413 * @return bool
414 */
415 public function is_settings_page() {
416 global $pagenow;
417
418 $page = htmlspecialchars( wp_unslash( $_GET['page'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended
419
420 if ( $this->get_settings_page_slug() !== $page ) {
421 return false;
422 }
423
424 if ( imagify_is_active_for_network() ) {
425 return 'admin.php' === $pagenow;
426 }
427
428 return 'options-general.php' === $pagenow;
429 }
430
431 /**
432 * Tell if we’re displaying the bulk optimization page.
433 *
434 * @since 1.9
435 *
436 * @return bool
437 */
438 public function is_bulk_page() {
439 global $pagenow;
440
441 $page = htmlspecialchars( wp_unslash( $_GET['page'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended
442
443 return 'upload.php' === $pagenow && $this->get_bulk_page_slug() === $page;
444 }
445
446 /**
447 * Tell if we’re displaying the custom files list page.
448 *
449 * @since 1.9
450 *
451 * @return bool
452 */
453 public function is_files_page() {
454 global $pagenow;
455
456 $page = htmlspecialchars( wp_unslash( $_GET['page'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended
457
458 return 'upload.php' === $pagenow && $this->get_files_page_slug() === $page;
459 }
460
461 /**
462 * Tell if we’re displaying the WP media library page.
463 *
464 * @since 1.9
465 *
466 * @return bool
467 */
468 public function is_wp_library_page() {
469 global $pagenow;
470
471 return 'upload.php' === $pagenow && ! isset( $_GET['page'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
472 }
473
474 /**
475 * Tell if we’re displaying a media page.
476 *
477 * @since 1.9
478 *
479 * @return bool
480 */
481 public function is_media_page() {
482 global $pagenow, $typenow;
483
484 return 'post.php' === $pagenow && 'attachment' === $typenow;
485 }
486
487
488 /** ----------------------------------------------------------------------------------------- */
489 /** QUOTA =================================================================================== */
490 /** ----------------------------------------------------------------------------------------- */
491
492 /**
493 * Get the remaining quota in percent.
494 *
495 * @since 1.8.1
496 *
497 * @return int
498 */
499 public function get_quota_percent() {
500 static $quota;
501
502 if ( isset( $quota ) ) {
503 return $quota;
504 }
505
506 $user = new User();
507 $quota = $user->get_percent_unconsumed_quota();
508
509 return $quota;
510 }
511
512 /**
513 * Get the HTML class used for the quota (to change the color when out of quota for example).
514 *
515 * @since 1.8.1
516 *
517 * @return string
518 */
519 public function get_quota_class() {
520 static $class;
521
522 if ( isset( $class ) ) {
523 return $class;
524 }
525
526 $quota = $this->get_quota_percent();
527 $class = 'imagify-bar-';
528
529 if ( $quota <= 20 ) {
530 $class .= 'negative';
531 } elseif ( $quota <= 50 ) {
532 $class .= 'neutral';
533 } else {
534 $class .= 'positive';
535 }
536
537 return $class;
538 }
539
540 /**
541 * Get the HTML tag used for the quota (the weather-like icon).
542 *
543 * @since 1.8.1
544 *
545 * @return string
546 */
547 public function get_quota_icon() {
548 static $icon;
549
550 if ( isset( $icon ) ) {
551 return $icon;
552 }
553
554 $quota = $this->get_quota_percent();
555
556 if ( $quota <= 20 ) {
557 $icon = '<img src="' . IMAGIFY_ASSETS_IMG_URL . 'stormy.svg" width="64" height="63" alt="" />';
558 } elseif ( $quota <= 50 ) {
559 $icon = '<img src="' . IMAGIFY_ASSETS_IMG_URL . 'cloudy-sun.svg" width="63" height="64" alt="" />';
560 } else {
561 $icon = '<img src="' . IMAGIFY_ASSETS_IMG_URL . 'sun.svg" width="63" height="64" alt="" />';
562 }
563
564 return $icon;
565 }
566
567
568 /** ----------------------------------------------------------------------------------------- */
569 /** GENERIC TEMPLATE TOOLS ================================================================== */
570 /** ----------------------------------------------------------------------------------------- */
571
572 /**
573 * Get a template contents.
574 *
575 * @since 1.7
576 *
577 * @param string $template The template name.
578 * @param mixed $data Some data to pass to the template.
579 * @return string|bool The page contents. False if the template doesn't exist.
580 */
581 public function get_template( $template, $data = array() ) {
582 $path = str_replace( '_', '-', $template );
583 $path = IMAGIFY_PATH . 'views/' . $template . '.php';
584
585 if ( ! $this->filesystem->exists( $path ) ) {
586 return false;
587 }
588
589 ob_start();
590 include $path;
591 $contents = ob_get_clean();
592
593 return trim( (string) $contents );
594 }
595
596 /**
597 * Print a template.
598 *
599 * @since 1.7
600 *
601 * @param string $template The template name.
602 * @param mixed $data Some data to pass to the template.
603 */
604 public function print_template( $template, $data = array() ) {
605 echo $this->get_template( $template, $data );
606 }
607
608 /**
609 * Add a template to the list of JS templates to print at the end of the page.
610 *
611 * @since 1.7
612 *
613 * @param string $template The template name.
614 */
615 public function print_js_template_in_footer( $template ) {
616 if ( isset( $this->templates_in_footer[ $template ] ) ) {
617 return;
618 }
619
620 if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
621 return;
622 }
623
624 switch ( $template ) {
625 case 'button/processing':
626 $data = [ 'label' => '{{ data.label }}' ];
627 break;
628 default:
629 $data = [];
630 }
631
632 $this->templates_in_footer[ $template ] = $data;
633 }
634
635 /**
636 * Print the JS templates that have been added to the "queue".
637 *
638 * @since 1.9
639 */
640 public function print_js_templates() {
641 if ( ! $this->templates_in_footer ) {
642 return;
643 }
644
645 foreach ( $this->templates_in_footer as $template => $data ) {
646 $template_id = str_replace( [ '/', '_' ], '-', $template );
647
648 echo '<script type="text/html" id="tmpl-imagify-' . $template_id . '">';
649 $this->print_template( $template, $data );
650 echo '</script>';
651 }
652 }
653
654
655 /** ----------------------------------------------------------------------------------------- */
656 /** TOOLS =================================================================================== */
657 /** ----------------------------------------------------------------------------------------- */
658
659 /**
660 * Create HTML attributes from an array.
661 *
662 * @since 1.9
663 *
664 * @param array $attributes A list of attribute pairs.
665 * @return string HTML attributes.
666 */
667 public function build_attributes( $attributes ) {
668 if ( ! $attributes || ! is_array( $attributes ) ) {
669 return '';
670 }
671
672 $out = '';
673
674 foreach ( $attributes as $attribute => $value ) {
675 if ( '' === $value ) {
676 continue;
677 }
678
679 $out .= ' ' . $attribute . '="' . esc_attr( $value ) . '"';
680 }
681
682 return $out;
683 }
684 }
685