PluginProbe
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF / trunk
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF vtrunk
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 / classes / Media / Subscriber.php

Subscriber.php in Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF trunk, at classes/Media/Subscriber.php

190 lines 5.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 declare(strict_types=1);
3
4 namespace Imagify\Media;
5
6 use Imagify\EventManagement\SubscriberInterface;
7 use Imagify\Media\Upload\Upload;
8 use Imagify\Optimization\NextGenMarker;
9 use WP_Query;
10
11 /**
12 * Media Subscriber
13 */
14 class Subscriber implements SubscriberInterface {
15
16 /**
17 * Upload instance.
18 *
19 * @var Upload
20 */
21 private $upload;
22 /**
23 * Constructor
24 *
25 * @param Upload $upload Upload Instance.
26 */
27 public function __construct( Upload $upload ) {
28 $this->upload = $upload;
29 }
30
31 /**
32 * Returns an array of events that this subscriber wants to listen to.
33 *
34 * @return array
35 */
36 public static function get_subscribed_events(): array {
37 return [
38 // @action
39 'restrict_manage_posts' => 'imagify_attachments_filter_dropdown',
40 // @action
41 'pre_get_posts' => 'filter_missing_nextgen_query',
42 ];
43 }
44
45 /**
46 * Adds a dropdown that allows filtering on the attachments Imagify status.
47 *
48 * @return void
49 */
50 public function imagify_attachments_filter_dropdown() {
51 if ( ! \Imagify_Views::get_instance()->is_wp_library_page() ) {
52 return;
53 }
54 $this->upload->add_imagify_filter_to_attachments_dropdown();
55 }
56
57 /**
58 * Narrows the Media Library list table (list mode only, `WP_Query`-based) to attachments that
59 * are optimized but have no successful next-gen size recorded, when
60 * `?imagify-status=missing-nextgen` is requested.
61 *
62 * The predicate mirrors `Imagify\Bulk\WP::get_optimized_media_ids_without_format()` on purpose:
63 * the list and the "missing next-gen" count it feeds must never disagree.
64 *
65 * @param WP_Query $query The current query, by reference.
66 *
67 * @return void
68 */
69 public function filter_missing_nextgen_query( WP_Query $query ) {
70 if ( ! is_admin() || ! $query->is_main_query() ) {
71 return;
72 }
73
74 if ( ! \Imagify_Views::get_instance()->is_wp_library_page() ) {
75 return;
76 }
77
78 $status = isset( $_GET['imagify-status'] ) ? sanitize_text_field( wp_unslash( $_GET['imagify-status'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
79
80 if ( 'missing-nextgen' !== $status ) {
81 return;
82 }
83
84 $formats = imagify_nextgen_images_formats();
85
86 if ( empty( $formats ) ) {
87 // No next-gen format is enabled: nothing can be "missing" a format that isn't
88 // generated in the first place. Show no results rather than the whole library.
89 $query->set( 'post__in', [ 0 ] );
90 return;
91 }
92
93 $format = $this->get_enabled_format( $formats );
94 $nextgen_suffix = $this->get_nextgen_suffix( $format );
95
96 if ( '' === $nextgen_suffix ) {
97 // The enabled format is not one we know how to detect: showing the whole library
98 // would be worse than showing nothing.
99 $query->set( 'post__in', [ 0 ] );
100 return;
101 }
102
103 $query->set(
104 'meta_query', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
105 [
106 'relation' => 'AND',
107 [
108 'key' => '_imagify_status',
109 'value' => [ 'success', 'already_optimized' ],
110 'compare' => 'IN',
111 ],
112 [
113 'key' => '_imagify_data',
114 'value' => NextGenMarker::success( $nextgen_suffix ),
115 'compare' => 'NOT LIKE',
116 ],
117 [
118 'key' => '_imagify_data',
119 'value' => NextGenMarker::permanent_error( $nextgen_suffix ),
120 'compare' => 'NOT LIKE',
121 ],
122 ]
123 );
124
125 if ( ! $query->get( 'post_mime_type' ) ) {
126 $query->set( 'post_mime_type', $this->get_convertible_mime_types( $format ) );
127 }
128 }
129
130 /**
131 * Reads the first enabled next-gen format.
132 *
133 * `imagify_nextgen_images_formats()` is filterable by third parties, so the array may come
134 * back as a list (`[ 'webp' ]`) rather than the keyed shape core builds (`[ 'webp' => 'webp' ]`).
135 * Reading the key would then yield the integer `0` — which is what made `strtoupper()` fatal
136 * on PHP 8 — so the value is read instead, and anything that is not a string is discarded.
137 *
138 * @param array $formats The enabled next-gen formats.
139 *
140 * @return string The format in lowercase, or an empty string if it is unusable.
141 */
142 private function get_enabled_format( array $formats ): string {
143 $format = current( $formats );
144
145 return is_string( $format ) ? strtolower( $format ) : '';
146 }
147
148 /**
149 * Resolves the next-gen suffix (e.g. `@imagify-webp`) for the given format.
150 *
151 * An unrecognised format resolves to an empty string rather than raising an error, since the
152 * format ultimately comes from a public filter.
153 *
154 * @param string $format The next-gen format, lowercase.
155 *
156 * @return string The suffix, or an empty string if the format is not recognised.
157 */
158 private function get_nextgen_suffix( string $format ): string {
159 $process_class = imagify_get_optimization_process_class_name( 'wp' );
160 $suffixes = [
161 'avif' => constant( $process_class . '::AVIF_SUFFIX' ),
162 'webp' => constant( $process_class . '::WEBP_SUFFIX' ),
163 ];
164
165 return isset( $suffixes[ $format ] ) ? $suffixes[ $format ] : '';
166 }
167
168 /**
169 * Lists the mime types that can hold a next-gen version of the given format.
170 *
171 * Mirrors `Imagify\Bulk\WP::get_optimized_media_ids_without_format()`: images only — a PDF has
172 * no next-gen version, so it can never be "missing" one — minus the target format's own mime
173 * type, since an image that already *is* WebP is not missing a WebP version.
174 *
175 * @param string $format The next-gen format being looked for, e.g. `webp`.
176 *
177 * @return array The mime types, as extension => mime type pairs.
178 */
179 private function get_convertible_mime_types( string $format ): array {
180 $mime_types = imagify_get_mime_types( 'image' );
181
182 return array_filter(
183 $mime_types,
184 function ( $mime ) use ( $format ) {
185 return 'image/' . strtolower( $format ) !== $mime;
186 }
187 );
188 }
189 }
190