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
← All changes | classes/Context/WP.php +118 -0 2.3.2 → trunk View file →
@@ -30,8 +30,19 @@
30 30 */
31 31 protected $resizing_threshold = 0;
32 32
33 33 /**
34 + * True once WordPress has said the browser is scaling the upload being created.
35 + *
36 + * Set on `rest_after_insert_attachment`, read by the threshold filter later in the same
37 + * request. One request creates one attachment, so there is nothing to key it by.
38 + *
39 + * @var bool
40 + * @since 2.3.3
41 + */
42 + protected $browser_is_scaling = false;
43 +
44 + /**
34 45 * Get the thumbnail sizes for this context, except the full size.
35 46 *
36 47 * @since 1.9
37 48 * @author Grégory Viguier
@@ -66,8 +77,115 @@
66 77 $this->resizing_threshold = max( 0, get_imagify_option( 'resize_larger_w' ) );
67 78 }
68 79
69 80 return $this->resizing_threshold;
81 + }
82 +
83 + /**
84 + * Filter WP's "big images threshold" with Imagify's resizing value.
85 + *
86 + * Imagify stands down for one case only: the upload WordPress 7.1 handed to the browser,
87 + * which supplies its own scaled file through the sideload endpoint. Scaling again on the
88 + * server would leave a conflicting "-scaled" file behind and point `original_image` at it
89 + * instead of the real upload, which is why core switches its own downscaling off there.
90 + *
91 + * Nothing is lost by standing down: the value the browser scales to is produced by this
92 + * same filter, in {@see WP_REST_Server::get_index()}, so Imagify's setting still governs
93 + * the result.
94 + *
95 + * A `false` coming from anywhere else is deliberately overridden, exactly as before. Only
96 + * the browser flow leaves a scaled file behind, so treating every `false` as "already
97 + * scaled" would mean an image nobody resized: not WordPress, because it was told not to,
98 + * and not Imagify, because it believed the work was done.
99 + *
100 + * @since 2.3.3
101 + *
102 + * @param int|false $threshold The threshold value in pixels, or false to disable resizing.
103 + * @return int|false
104 + */
105 + public function filter_big_image_size_threshold( $threshold ) {
106 + if ( false === $threshold && $this->browser_is_scaling ) {
107 + return $threshold;
108 + }
109 +
110 + return $this->get_resizing_threshold();
111 + }
112 +
113 + /**
114 + * Remember that the browser is supplying the scaled version of an attachment.
115 + *
116 + * Taken from where WordPress declares it rather than guessed: this runs on
117 + * `rest_after_insert_attachment`, just before the metadata is generated, and the request
118 + * carries `generate_sub_sizes` as `false` exactly when the browser owns the sub sizes.
119 + *
120 + * @since 2.3.3
121 + *
122 + * The threshold filter runs later in this same request, so a property is enough for it. The
123 + * transient is for the optimization, which runs in a later request of its own.
124 + *
125 + * @param object $attachment Inserted or updated attachment object. A \WP_Post when WordPress fires this.
126 + * @param object $request Request object. A \WP_REST_Request when WordPress fires this.
127 + * @param bool $creating True when creating an attachment, false when updating.
128 + */
129 + public function maybe_flag_client_side_scaling( $attachment, $request, $creating ) {
130 + if ( ! $creating || ! is_object( $attachment ) || ! isset( $attachment->ID ) ) {
131 + return;
132 + }
133 +
134 + if ( ! is_object( $request ) || ! is_callable( [ $request, 'get_param' ] ) ) {
135 + return;
136 + }
137 +
138 + if ( false !== $request->get_param( 'generate_sub_sizes' ) ) {
139 + return;
140 + }
141 +
142 + $this->browser_is_scaling = true;
143 +
144 + self::flag_client_side_scaling( $attachment->ID );
145 + }
146 +
147 + /**
148 + * Remember that the browser is supplying the scaled version of an attachment.
149 + *
150 + * Optimization runs in a later, asynchronous request, where the filters WordPress
151 + * set up during the upload are long gone, so the state has to be stored.
152 + *
153 + * The flag is left to expire rather than deleted after use: it is read once per size
154 + * being optimized, so deleting it on the first read would let the remaining sizes
155 + * resize the file. An hour is far longer than the queue needs, and the pattern is
156 + * registered in {@see \Imagify\Tools\InternalStateList} so a reset clears it.
157 + *
158 + * @since 2.3.3
159 + *
160 + * @param int $attachment_id Attachment post ID.
161 + */
162 + public static function flag_client_side_scaling( $attachment_id ) {
163 + set_transient( self::get_client_side_scaling_flag( $attachment_id ), 1, HOUR_IN_SECONDS );
164 + }
165 +
166 + /**
167 + * Tell if the browser supplied the scaled version of an attachment.
168 + *
169 + * @since 2.3.3
170 + *
171 + * @param int $attachment_id Attachment post ID.
172 + * @return bool
173 + */
174 + public static function is_client_side_scaled( $attachment_id ) {
175 + return (bool) get_transient( self::get_client_side_scaling_flag( $attachment_id ) );
176 + }
177 +
178 + /**
179 + * Get the transient name used to flag client side scaling for an attachment.
180 + *
181 + * @since 2.3.3
182 + *
183 + * @param int $attachment_id Attachment post ID.
184 + * @return string
185 + */
186 + private static function get_client_side_scaling_flag( $attachment_id ) {
187 + return 'imagify_client_side_scaled_' . (int) $attachment_id;
70 188 }
71 189
72 190 /**
73 191 * Tell if the optimization process is allowed to backup in this context.