PluginProbe ʕ •ᴥ•ʔ
Admin and Site Enhancements (ASE) / 7.8.1
Admin and Site Enhancements (ASE) v7.8.1
9.1.0 9.0.2 9.0.1 9.0.0 8.9.2 8.9.1 8.9.0 8.8.8 8.8.7 8.8.6 8.8.5 8.8.4 8.8.3 8.8.2 8.8.1 8.8.0 8.7.3 8.7.2 8.7.1 8.2.1 8.2.2 8.2.3 8.3.0 8.3.1 8.3.2 8.4.0 8.4.1 8.4.2 8.5.0 8.5.1 8.5.2 8.6.0 8.6.1 8.6.2 8.7.0 5.0.1 5.0.2 5.0.2.1 5.0.2.2 5.0.2.3 5.0.2.4 5.1.0 5.2.0 5.2.1 5.2.10 5.2.11 5.2.2 5.2.3 5.2.4 5.2.5 5.2.6 5.2.7 5.2.8 5.2.9 5.3.0 5.3.1 5.3.2 5.4.0 5.4.1 5.5.0 5.5.1 5.5.2 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.8.0 5.8.1 6.0.0 6.0.3 6.0.4 6.0.5 6.0.5.1 6.0.6 6.0.7 6.0.8.1 6.1.0 6.1.3 6.2.0 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.2.6 6.2.7 6.3.0 6.3.1 6.3.2 6.4.0 6.5.0 6.5.1 6.6.0 6.7.0 6.8.0 6.8.2 6.8.3 6.9.0 6.9.1 6.9.10 6.9.11 6.9.12 6.9.13.1 6.9.13.2 6.9.2 6.9.3 6.9.4 6.9.5 6.9.6 6.9.7 6.9.8 6.9.9 7.0.0 7.0.2 7.0.2.1 7.0.2.2 7.0.2.3 7.0.3 7.1.0 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2.0 7.2.1 7.3.0 7.3.1 7.3.2 7.3.3 7.4.0 7.4.2 7.4.4 7.4.5 7.4.6 7.4.7 7.4.8 7.5.0 7.5.1 7.5.2 7.5.3 7.5.4 7.6.0 7.6.1 7.6.1.1 7.6.10 7.6.11 7.6.2 7.6.3 7.6.4 7.6.5 7.6.6 7.6.7 7.6.7.1 7.6.8 7.6.9 7.7.0 7.8.0 7.8.1 7.8.10 7.8.11 7.8.12 7.8.13 7.8.14 7.8.15 7.8.16 7.8.17 7.8.18 7.8.2 7.8.3 7.8.4 7.8.5 7.8.5.1 7.8.6 7.8.7 7.8.8 7.8.9 7.9.0 7.9.1 7.9.10 7.9.11 7.9.2 7.9.3 7.9.4 7.9.5 7.9.6 7.9.7 7.9.8 7.9.9 8.0.0 8.0.1 8.0.2 8.0.3 8.0.4 8.0.5 8.0.6 8.0.7 8.0.8 8.1.0 8.1.1 8.1.2 8.1.3 8.1.4 8.2.0 trunk 1.0.0 1.1.0 1.2.0 1.3.0 1.4.0 1.5.0 1.6.0 1.7.0 1.8.0 1.9.0 2.0.0 2.1.0 2.2.0 2.3.0 2.4.0 2.5.0 2.6.0 2.7.0 2.8.0 2.8.1 2.8.2 2.8.3 2.9.0 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.1.0 3.2.0 3.3.0 3.4.0 3.5.0 3.6.1 3.7.0 3.8.0 3.9.0 3.9.1 3.9.2 4.0.0 4.0.1 4.1.0 4.2.0 4.2.1 4.2.2 4.3.0 4.3.1 4.4.0 4.5.0 4.6.0 4.7.0 4.7.1 4.7.2 4.7.3 4.7.4 4.8.0 4.8.1 4.8.2 4.8.3 4.9.0 4.9.1 4.9.2 4.9.3 5.0.0
admin-site-enhancements / classes / class-media-replacement.php
admin-site-enhancements / classes Last commit date
class-activation.php 1 year ago class-admin-menu-organizer.php 1 year ago class-auto-publish-posts-with-missed-schedule.php 1 year ago class-avif-upload.php 1 year ago class-captcha-protection.php 1 year ago class-change-login-url.php 1 year ago class-cleanup-admin-bar.php 1 year ago class-common-methods.php 1 year ago class-content-duplication.php 1 year ago class-content-order.php 1 year ago class-custom-admin-footer-text.php 1 year ago class-custom-body-class.php 1 year ago class-custom-css.php 1 year ago class-custom-nav-menu-items-in-new-tab.php 1 year ago class-deactivation.php 1 year ago class-disable-comments.php 1 year ago class-disable-dashboard-widgets.php 1 year ago class-disable-feeds.php 1 year ago class-disable-gutenberg.php 1 year ago class-disable-rest-api.php 1 year ago class-disable-smaller-components.php 1 year ago class-disable-updates.php 1 year ago class-disable-xml-rpc.php 1 year ago class-display-system-summary.php 1 year ago class-email-address-obfuscator.php 1 year ago class-email-delivery.php 1 year ago class-enhance-list-tables.php 1 year ago class-external-permalinks.php 1 year ago class-heartbeat-control.php 1 year ago class-hide-admin-bar.php 1 year ago class-hide-admin-notices.php 1 year ago class-image-sizes-panel.php 1 year ago class-image-upload-control.php 1 year ago class-insert-head-body-footer-code.php 1 year ago class-last-login-column.php 1 year ago class-limit-login-attempts.php 1 year ago class-login-id-type.php 1 year ago class-login-logout-menu.php 1 year ago class-maintenance-mode.php 1 year ago class-manage-ads-appads-txt.php 1 year ago class-manage-robots-txt.php 1 year ago class-media-replacement.php 1 year ago class-multiple-user-roles.php 1 year ago class-obfuscate-author-slugs.php 1 year ago class-open-external-links-in-new-tab.php 1 year ago class-password-protection.php 1 year ago class-redirect-after-login.php 1 year ago class-redirect-after-logout.php 1 year ago class-redirect-fourofour.php 1 year ago class-registration-date-column.php 1 year ago class-revisions-control.php 1 year ago class-search-engines-visibility.php 1 year ago class-settings-fields-render.php 1 year ago class-settings-sanitization.php 1 year ago class-settings-sections-fields.php 1 year ago class-show-custom-taxonomy-filters.php 1 year ago class-site-identity-on-login-page.php 1 year ago class-svg-upload.php 1 year ago class-various-admin-ui-enhancements.php 1 year ago class-view-admin-as-role.php 1 year ago class-wider-admin-menu.php 1 year ago class-wp-config-transformer.php 1 year ago
class-media-replacement.php
385 lines
1 <?php
2
3 namespace ASENHA\Classes;
4
5 /**
6 * Class for Media Replacement module
7 *
8 * @since 6.9.5
9 */
10 class Media_Replacement {
11
12 /**
13 * Modify the 'Edit' link to be 'Edit or Replace'
14 *
15 */
16 public function modify_media_list_table_edit_link( $actions, $post ) {
17
18 $new_actions = array();
19
20 foreach( $actions as $key => $value ) {
21
22 if ( $key == 'edit' ) {
23
24 $new_actions['edit'] = '<a href="' . get_edit_post_link( $post ) . '" aria-label="Edit or Replace">Edit or Replace</a>';
25
26 } else {
27
28 $new_actions[$key] = $value;
29
30 }
31
32 }
33
34 return $new_actions;
35
36 }
37
38 /**
39 * Add media replacement button in the edit screen of media/attachment
40 *
41 * @since 1.1.0
42 */
43 public function add_media_replacement_button( $fields, $post ) {
44 global $pagenow, $typenow;
45
46 // Do not do this on post creation and editing screen
47 // May cause media frame layout / display issues
48 if ( 'attachment' == $typenow ||
49 ( 'attachment' != $typenow && 'post-new.php' != $pagenow && 'post.php' != $pagenow )
50 ) {
51 $original_attachment_id = '';
52 $image_mime_type = '';
53 if ( is_object( $post ) ) {
54 $original_attachment_id = $post->ID;
55 if ( property_exists( $post, 'post_mime_type' ) ) {
56 $image_mime_type = $post->post_mime_type;
57 }
58 }
59
60 // Enqueues all scripts, styles, settings, and templates necessary to use all media JS APIs.
61 // Reference: https://codex.wordpress.org/Javascript_Reference/wp.media
62 wp_enqueue_media();
63
64 // Add new field to attachment fields for the media replace functionality
65 $fields['asenha-media-replace'] = array();
66 $fields['asenha-media-replace']['label'] = '';
67 $fields['asenha-media-replace']['input'] = 'html';
68 $fields['asenha-media-replace']['html'] = '
69 <div id="media-replace-div' . '" class="postbox attachment-id-' . $original_attachment_id . '" data-original-image-id="' . $original_attachment_id . '">
70 <div class="postbox-header">
71 <h2 class="hndle ui-sortable-handle">' . __( 'Replace Media', 'admin-site-enhancements' ) . '</h2>
72 </div>
73 <div class="inside">
74 <button type="button" id="asenha-media-replace" class="button-secondary button-large asenha-media-replace-button" data-old-image-mime-type="' . $image_mime_type . '" onclick="replaceMedia(\'' . $original_attachment_id . '\',\'' . $image_mime_type . '\');">' . __( 'Select New Media File', 'admin-site-enhancements' ) . '</button>
75 <input type="hidden" id="new-attachment-id-' . $original_attachment_id . '" name="new-attachment-id-' . $original_attachment_id . '" />
76 <div class="asenha-media-replace-notes"><p>' . __( 'The current file will be replaced with the uploaded / selected file (of the same type) while retaining the current ID, publish date and file name. Thus, no existing links will break.', 'admin-site-enhancements' ) . '</p></div>
77 </div>
78 </div>
79 ';
80 }
81
82 return $fields;
83
84 }
85
86 public function attachment_for_js( $image_url, $attachment_id ) {
87 // vi( $image_url );
88 // vi( $attachment_id );
89 }
90
91 /**
92 * Replace existing media with the newly updated file
93 *
94 * @link https://plugins.trac.wordpress.org/browser/replace-image/tags/1.1.7/hm-replace-image.php#L55
95 * @since 1.1.0
96 */
97 public function replace_media( $old_attachment_id ) {
98 // vi( $old_attachment_id, '', 'replace_media has been triggered via edit_attachment_hook' );
99
100 // Get the new attachment/media ID, meta and mime type
101 if ( isset( $_POST['new-attachment-id-'.$old_attachment_id] ) && ! empty( $_POST['new-attachment-id-'.$old_attachment_id] ) ) {
102 $new_attachment_id = intval( sanitize_text_field( $_POST['new-attachment-id-'.$old_attachment_id] ) );
103 // vi( $new_attachment_id, '', '$new_attachment_id is detected in replace_media' );
104
105 $old_post_meta = get_post( $old_attachment_id, ARRAY_A );
106 $old_post_mime = $old_post_meta['post_mime_type']; // e.g. 'image/jpeg'
107 // vi( $old_post_mime, '', 'old_post_mime is detected in replace_media' );
108
109 $new_post_meta = get_post( $new_attachment_id, ARRAY_A );
110 $new_post_mime = $new_post_meta['post_mime_type']; // e.g. 'image/jpeg'
111 // vi( $new_post_mime, '', 'new_post_mime is detected in replace_media' );
112
113 // Check if the media file ID selected via the media frame and passed on to the #new-attachment-id hidden field
114 // Ensure the mime type matches too
115 if ( ( ! empty( $new_attachment_id ) ) && is_numeric( $new_attachment_id ) && ( $old_post_mime == $new_post_mime ) ) {
116 // vi( $new_attachment_id, '', 'We are processing the replacement of the old image.' );
117
118 $new_attachment_meta = wp_get_attachment_metadata( $new_attachment_id );
119
120 // If original file is larger than 2560 pixel
121 // https://make.wordpress.org/core/2019/10/09/introducing-handling-of-big-images-in-wordpress-5-3/
122 if ( array_key_exists( 'original_image', $new_attachment_meta ) ) {
123
124 // Get the original media file path
125 $new_media_file_path = wp_get_original_image_path( $new_attachment_id );
126
127 } else {
128
129 // Get the path to newly uploaded media file. An image file name may end with '-scaled'.
130 $new_attachment_file = get_post_meta( $new_attachment_id, '_wp_attached_file', true );
131 $upload_dir = wp_upload_dir();
132 $new_media_file_path = $upload_dir['basedir'] . '/' . $new_attachment_file;
133
134 }
135
136 // Check if the new media file exist / was successfully uploaded
137 if ( ! is_file( $new_media_file_path ) ) {
138 return false;
139 }
140
141 // Delete existing/old media files. Post and post meta entries for it are still there in the database.
142 $this->delete_media_files( $old_attachment_id );
143
144 // If original file is larger than 2560 pixel
145 // https://make.wordpress.org/core/2019/10/09/introducing-handling-of-big-images-in-wordpress-5-3/
146 if ( array_key_exists( 'original_image', $new_attachment_meta ) ) {
147
148 // Get the original media file path
149 $old_media_file_path = wp_get_original_image_path( $old_attachment_id );
150
151 } else {
152
153 // Get the path to the old/existing media file that will be replaced and deleted. An image file name may end with '-scaled'.
154 $old_attachment_file = get_post_meta( $old_attachment_id, '_wp_attached_file', true );
155 $old_media_file_path = $upload_dir['basedir'] . '/' . $old_attachment_file;
156
157 }
158
159 // Check if the directory path to the old media file is still intact
160 if ( ! file_exists( dirname( $old_media_file_path ) ) ) {
161
162 // Recreate the directory path
163 mkdir( dirname( $old_media_file_path ), 0755, true );
164
165 }
166
167 // Copy the new media file into the old media file's path
168 copy( $new_media_file_path, $old_media_file_path );
169
170 // Regenerate attachment meta data and image sub-sizes from the new media file that was just copied to the old path
171 $old_media_post_meta_updated = wp_generate_attachment_metadata( $old_attachment_id, $old_media_file_path );
172
173 // Update new media file's meta data with the ones from the old media. i.e. new media file will carry over the post ID and post meta of the old media file. i.e. only the files are replaced for the old media's ID and post meta in the database.
174 wp_update_attachment_metadata( $old_attachment_id, $old_media_post_meta_updated );
175
176 // Delete the newly uploaded media file and it's sub-sizes, and also delete post and post meta entries for it in the database.
177 wp_delete_attachment( $new_attachment_id, true );
178
179 // Add old attachment ID to recently replaced media option. This will be used for cache busting to ensure the new replacement images are immediately loaded in the browser / wp-admin
180 $options_extra = get_option( ASENHA_SLUG_U . '_extra', array() );
181 $recently_replaced_media = isset( $options_extra['recently_replaced_media'] ) ? $options_extra['recently_replaced_media'] : array();
182 $max_media_number_to_cache_bust = 5;
183 // vi( $recently_replaced_media, '', 'before' );
184 if ( count( $recently_replaced_media ) >= $max_media_number_to_cache_bust ) {
185 // Remove first/oldest attachment ID
186 array_shift( $recently_replaced_media );
187 }
188 $recently_replaced_media[] = $old_attachment_id;
189 $recently_replaced_media = array_unique( $recently_replaced_media );
190 // vi( $recently_replaced_media, '', 'after' );
191 $options_extra['recently_replaced_media'] = $recently_replaced_media;
192 update_option( ASENHA_SLUG_U . '_extra', $options_extra, true );
193 sleep(2);
194 }
195 }
196 }
197
198 /**
199 * Delete the existing/old media files when performing media replacement
200 *
201 * @link https://plugins.trac.wordpress.org/browser/replace-image/tags/1.1.7/hm-replace-image.php#L80
202 * @since 1.1.0
203 */
204 public function delete_media_files( $post_id ) {
205
206 $attachment_meta = wp_get_attachment_metadata( $post_id );
207
208 // Will get '-scaled' version if it exists, e.g. /path/to/uploads/year/month/file-name.jpg
209 $attachment_file_path = get_attached_file( $post_id );
210
211 // e.g. file-name.jpg
212 $attachment_file_basename = basename( $attachment_file_path );
213
214 // Delete intermediate images if there are any
215
216 if ( isset( $attachment_meta['sizes'] ) && is_array( $attachment_meta['sizes'] ) ) {
217
218 foreach( $attachment_meta['sizes'] as $size => $size_info) {
219
220 // /path/to/uploads/year/month/file-name.jpg --> /path/to/uploads/year/month/file-name-1024x768.jpg
221 $intermediate_file_path = str_replace( $attachment_file_basename, $size_info['file'], $attachment_file_path );
222 wp_delete_file( $intermediate_file_path );
223
224 }
225
226 }
227
228 // Delete the attachment file, which maybe the '-scaled' version
229 wp_delete_file( $attachment_file_path );
230
231 // If original file is larger than 2560 pixel
232 // https://make.wordpress.org/core/2019/10/09/introducing-handling-of-big-images-in-wordpress-5-3/
233 $attachment_original_file_path = wp_get_original_image_path( $post_id );
234
235 // Maybe delete the original file if it's an image file, and the original file path exists / was found
236 if ( $attachment_original_file_path ) {
237 wp_delete_file( $attachment_original_file_path );
238 }
239
240 }
241
242 /**
243 * Customize the attachment updated message
244 *
245 * @link https://github.com/WordPress/wordpress-develop/blob/6.0.2/src/wp-admin/edit-form-advanced.php#L180
246 * @since 1.1.0
247 */
248 public function attachment_updated_custom_message( $messages ) {
249
250 $new_messages = array();
251
252 foreach( $messages as $post_type => $messages_array ) {
253
254 if ( $post_type == 'attachment' ) {
255
256 // Message ID for successful edit/update of an attachment is 4. e.g. /wp-admin/post.php?post=a&action=edit&classic-editor&message=4 Customize it here.
257 $messages_array[4] = 'Media file updated. You may need to <a href="https://fabricdigital.co.nz/blog/how-to-hard-refresh-your-browser-and-clear-cache" target="_blank">hard refresh</a> your browser to see the updated media preview image below.';
258
259 }
260
261 $new_messages[$post_type] = $messages_array;
262
263 }
264
265 return $new_messages;
266
267 }
268
269 /**
270 * Append cache busting parameter to the end of image srcset
271 *
272 * @since 5.7.0
273 */
274 public function append_cache_busting_param_to_image_srcset( $sources, $size_array, $image_src, $image_meta, $attachment_id ) {
275 $options_extra = get_option( ASENHA_SLUG_U . '_extra', array() );
276 $recently_replaced_media = isset( $options_extra['recently_replaced_media'] ) ? $options_extra['recently_replaced_media'] : array();
277 $attachment_mime_type = get_post_mime_type( $attachment_id );
278
279 if ( in_array( $attachment_id, $recently_replaced_media )
280 && false !== strpos( $attachment_mime_type, 'image' )
281 ) {
282 foreach ( $sources as $size => $source ) {
283 $source['url'] .= $this->maybe_append_timestamp_parameter( $source['url'] );
284 $sources[$size] = $source;
285 // vi( $source, '', 'cache busting added via append_cache_busting_param_to_image_srcset' );
286 }
287 }
288 return $sources;
289 }
290
291 /**
292 * Append cache busting parameter to the end of image src
293 *
294 * @since 5.7.0
295 */
296 public function append_cache_busting_param_to_attachment_image_src( $image, $attachment_id ) {
297 $options_extra = get_option( ASENHA_SLUG_U . '_extra', array() );
298 $recently_replaced_media = isset( $options_extra['recently_replaced_media'] ) ? $options_extra['recently_replaced_media'] : array();
299 $attachment_mime_type = get_post_mime_type( $attachment_id );
300
301 if ( ! empty( $image[0] )
302 && in_array( $attachment_id, $recently_replaced_media )
303 && false !== strpos( $attachment_mime_type, 'image' )
304 ) {
305 $image[0] .= $this->maybe_append_timestamp_parameter( $image[0] );
306 // vi( $image, '', 'cache busting added via append_cache_busting_param_to_attachment_image_src' );
307 }
308
309 return $image;
310 }
311
312 /**
313 * Append cache busting parameter to image src for js
314 *
315 * @since 5.7.0
316 */
317 public function append_cache_busting_param_to_attachment_for_js( $response, $attachment ) {
318 $options_extra = get_option( ASENHA_SLUG_U . '_extra', array() );
319 $recently_replaced_media = isset( $options_extra['recently_replaced_media'] ) ? $options_extra['recently_replaced_media'] : array();
320 $attachment_mime_type = get_post_mime_type( $attachment->ID );
321
322 if ( in_array( $attachment->ID, $recently_replaced_media )
323 && false !== strpos( $attachment_mime_type, 'image' )
324 ) {
325 if ( false !== strpos( $response['url'], '?' ) ) {
326 $response['url'] .= $this->maybe_append_timestamp_parameter( $response['url'] );
327 // vi( $response, '', 'cache busting added via append_cache_busting_param_to_attachment_for_js' );
328 }
329 if ( isset( $response['sizes'] ) ) {
330 foreach ( $response['sizes'] as $size_name => $size ) {
331 $response['sizes'][$size_name]['url'] .= $this->maybe_append_timestamp_parameter( $size['url'] );
332 // vi( $response, '', 'cache busting added via append_cache_busting_param_to_attachment_for_js' );
333 }
334 }
335 }
336
337 return $response;
338 }
339
340 /**
341 * Append cache busting parameter to attachment URL
342 *
343 * @since 6.8.2
344 */
345 public function append_cache_busting_param_to_attachment_url( $url, $attachment_id ) {
346 $options_extra = get_option( ASENHA_SLUG_U . '_extra', array() );
347 $recently_replaced_media = isset( $options_extra['recently_replaced_media'] ) ? $options_extra['recently_replaced_media'] : array();
348 $attachment_mime_type = get_post_mime_type( $attachment_id );
349
350 if ( in_array( $attachment_id, $recently_replaced_media )
351 && false !== strpos( $attachment_mime_type, 'image' )
352 ) {
353 $url .= $this->maybe_append_timestamp_parameter( $url );
354 // vi( $url, '', 'cache busting added via append_cache_busting_param_to_attachment_url' );
355 }
356
357 return $url;
358 }
359
360 /**
361 * Maybe append timestamp parameter
362 *
363 * @since 7.7
364 */
365 public function maybe_append_timestamp_parameter( $url ) {
366 $parts = parse_url( $url );
367 $additional_url_parameter = '';
368
369 if ( isset( $parts['query'] ) ) {
370 parse_str( $parts['query'], $query );
371
372 if ( isset( $query['t'] ) && ! empty( $query['t'] ) ) {
373 // Do not add another timestamp parameter
374 } else {
375 $additional_url_parameter = ( false === strpos( $url, '?' ) ? '?' : '&' ) . 't=' . time();
376 }
377
378 } else {
379 $additional_url_parameter = ( false === strpos( $url, '?' ) ? '?' : '&' ) . 't=' . time();
380 }
381
382 return $additional_url_parameter;
383 }
384
385 }