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 / Context / WP.php

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

253 lines 7.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Imagify\Context;
3
4 use Imagify\Traits\InstanceGetterTrait;
5
6 /**
7 * Context class used for the WP media library.
8 *
9 * @since 1.9
10 * @author Grégory Viguier
11 */
12 final class WP extends AbstractContext {
13 use InstanceGetterTrait;
14
15 /**
16 * Context "short name".
17 *
18 * @var string
19 * @since 1.9
20 * @author Grégory Viguier
21 */
22 protected $context = 'wp';
23
24 /**
25 * Images max width for this context. This is used when resizing.
26 *
27 * @var int
28 * @since 1.9.8
29 * @author Grégory Viguier
30 */
31 protected $resizing_threshold = 0;
32
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 /**
45 * Get the thumbnail sizes for this context, except the full size.
46 *
47 * @since 1.9
48 * @author Grégory Viguier
49 *
50 * @return array {
51 * Data for the currently registered thumbnail sizes.
52 * Size names are used as array keys.
53 *
54 * @type int $width The image width.
55 * @type int $height The image height.
56 * @type bool $crop True to crop, false to resize.
57 * @type string $name The size name.
58 * }
59 */
60 public function get_thumbnail_sizes() {
61 $this->thumbnail_sizes = get_imagify_thumbnail_sizes();
62
63 return $this->thumbnail_sizes;
64 }
65
66 /**
67 * Get images max width for this context. This is used when resizing.
68 * 0 means to not resize.
69 *
70 * @since 1.9.8
71 * @author Grégory Viguier
72 *
73 * @return int
74 */
75 public function get_resizing_threshold() {
76 if ( get_imagify_option( 'resize_larger' ) ) {
77 $this->resizing_threshold = max( 0, get_imagify_option( 'resize_larger_w' ) );
78 }
79
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;
188 }
189
190 /**
191 * Tell if the optimization process is allowed to backup in this context.
192 *
193 * @since 1.9
194 * @author Grégory Viguier
195 *
196 * @return bool
197 */
198 public function can_backup() {
199 $this->can_backup = get_imagify_option( 'backup' );
200
201 return $this->can_backup;
202 }
203
204 /**
205 * Get user capacity to operate Imagify in this context.
206 *
207 * @since 1.9
208 * @author Grégory Viguier
209 *
210 * @param string $describer Capacity describer. Possible values are like 'manage', 'bulk-optimize', 'manual-optimize', 'auto-optimize'.
211 * @return string
212 */
213 public function get_capacity( $describer ) {
214 static $edit_attachment_cap;
215
216 switch ( $describer ) {
217 case 'manage':
218 $capacity = imagify_is_active_for_network() ? 'manage_network_options' : 'manage_options';
219 break;
220
221 case 'bulk-optimize':
222 $capacity = 'manage_options';
223 break;
224
225 case 'optimize':
226 case 'restore':
227 // This is a generic capacity: don't use it unless you have no other choices!
228 if ( ! isset( $edit_attachment_cap ) ) {
229 $edit_attachment_cap = get_post_type_object( 'attachment' );
230 $edit_attachment_cap = $edit_attachment_cap ? $edit_attachment_cap->cap->edit_posts : 'edit_posts';
231 }
232
233 $capacity = $edit_attachment_cap;
234 break;
235
236 case 'manual-optimize':
237 case 'manual-restore':
238 // Must be used with an Attachment ID.
239 $capacity = 'edit_post';
240 break;
241
242 case 'auto-optimize':
243 $capacity = 'upload_files';
244 break;
245
246 default:
247 $capacity = $describer;
248 }
249
250 return $this->filter_capacity( $capacity, $describer );
251 }
252 }
253