-
Notifications
You must be signed in to change notification settings - Fork 34
Expand file tree
/
Copy pathmwebp.php
More file actions
270 lines (263 loc) · 10.8 KB
/
mwebp.php
File metadata and controls
270 lines (263 loc) · 10.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
<?php
/**
* Functions to migrate WebP files from the extension replacement to extension appending.
*
* @link https://ewww.io
* @package EWWW_Image_Optimizer
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Displays the bulk migration form.
*/
function ewww_image_optimizer_webp_migrate_preview() {
ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
$naming_mode = ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_naming_mode', 'append' );
?>
<div class="wrap">
<h1><?php esc_html_e( 'Rename WebP Images', 'ewww-image-optimizer' ); ?></h1>
<p>
<?php if ( 'replace' === $naming_mode ) : ?>
<?php esc_html_e( 'This tool will search your entire WordPress folder for images with a .webp extension appended and convert them to replacement naming.', 'ewww-image-optimizer' ); ?>
<?php else : ?>
<?php esc_html_e( 'This tool will search your entire WordPress folder for images with a .webp extension in place of the original, and append the extension instead.', 'ewww-image-optimizer' ); ?>
<?php endif; ?>
</p>
<div id="webp-loading"></div>
<div id="webp-progressbar"></div>
<div id="webp-counter"></div>
<div id="webp-status"></div>
<div id="bulk-forms">
<form id="webp-start" class="webp-form" method="post" action="">
<input id="webp-first" type="submit" class="button-secondary action" value="<?php esc_attr_e( 'Start Migration', 'ewww-image-optimizer' ); ?>" />
</form>
</div>
</div>
<?php
}
/**
* Scan a folder for webp images using the old naming scheme and return them as an array.
*
* @return array A list of images with the old naming scheme.
*/
function ewww_image_optimizer_webp_scan() {
ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
$list = array();
$dir = get_home_path();
$iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $dir ), RecursiveIteratorIterator::CHILD_FIRST );
$start = microtime( true );
$file_counter = 0;
$naming_mode = ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_naming_mode', 'append' );
$original_extensions = array( 'png', 'jpg', 'jpeg', 'gif' );
if ( ewww_image_optimizer_stl_check() ) {
set_time_limit( 0 );
}
foreach ( $iterator as $path ) {
if ( $path->isDir() ) {
continue;
} else {
++$file_counter;
$path = $path->getPathname();
if ( ! str_ends_with( $path, '.webp' ) ) {
continue;
}
$original_path = ewwwio()->remove_from_end( $path, '.webp' );
$info = pathinfo( $original_path );
$ext = strtolower( $info['extension'] ?? '' );
$is_real_ext = in_array( $ext, $original_extensions, true );
$plugins_dir = plugin_dir_path( EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH );
if ( str_contains( $path, $plugins_dir ) ) {
continue;
}
if ( 'append' === $naming_mode ) {
if ( $is_real_ext ) {
continue;
}
foreach ( $original_extensions as $ext ) {
if ( ewwwio_is_file( $original_path . '.' . $ext ) || ewwwio_is_file( $original_path . '.' . strtoupper( $ext ) ) ) {
ewwwio_debug_message( "queued $path" );
$list[] = $path;
break;
}
}
} elseif ( 'replace' === $naming_mode ) {
if ( ! $is_real_ext ) {
continue;
}
if ( ewwwio_is_file( $original_path ) ) {
ewwwio_debug_message( "queued $path" );
$list[] = $path;
}
}
}
}
$end = microtime( true ) - $start;
ewwwio_debug_message( "query time for $file_counter files (seconds): $end" );
return $list;
}
/**
* Prepares the migration and includes the javascript functions.
*
* @param string $hook The hook identifier for the current page.
*/
function ewww_image_optimizer_webp_script( $hook ) {
ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
// Make sure we are being called from the migration page.
if ( 'admin_page_ewww-image-optimizer-webp-migrate' !== $hook ) {
return;
}
$images = ewww_image_optimizer_webp_scan();
// Remove the images array from the db if it currently exists, and then store the new list in the database.
if ( get_option( 'ewww_image_optimizer_webp_images' ) ) {
delete_option( 'ewww_image_optimizer_webp_images' );
}
if ( get_option( 'ewww_image_optimizer_webp_skipped' ) ) {
delete_option( 'ewww_image_optimizer_webp_skipped' );
}
wp_enqueue_script( 'ewwwwebpscript', plugins_url( '/includes/webp.js', __FILE__ ), array( 'jquery' ), EWWW_IMAGE_OPTIMIZER_VERSION );
$image_count = count( $images );
// Submit a couple variables to the javascript to work with.
wp_localize_script(
'ewwwwebpscript',
'ewww_vars',
array(
'ewww_wpnonce' => wp_create_nonce( 'ewww-image-optimizer-webp' ),
'interrupted' => esc_html__( 'Operation Interrupted', 'ewww-image-optimizer' ),
'retrying' => esc_html__( 'Temporary failure, attempts remaining:', 'ewww-image-optimizer' ),
'invalid_response' => esc_html__( 'Received an invalid response from your website, please check for errors in the Developer Tools console of your browser.', 'ewww-image-optimizer' ),
'image_count' => $image_count,
'webp_images' => $images,
)
);
}
/**
* Called by javascript to initialize some output.
*/
function ewww_image_optimizer_webp_initialize() {
// Verify that an authorized user has started the migration.
$permissions = apply_filters( 'ewww_image_optimizer_admin_permissions', '' );
if ( empty( $_REQUEST['ewww_wpnonce'] ) || ! wp_verify_nonce( sanitize_key( $_REQUEST['ewww_wpnonce'] ), 'ewww-image-optimizer-webp' ) || ! current_user_can( $permissions ) ) {
ewwwio_ob_clean();
die( esc_html__( 'Access denied.', 'ewww-image-optimizer' ) );
}
// Generate the WP spinner image for display.
$loading_image = plugins_url( '/images/wpspin.gif', __FILE__ );
// Let the user know that we are beginning.
ewwwio_ob_clean();
die( '<p>' . esc_html__( 'Scanning', 'ewww-image-optimizer' ) . ' <img src="' . esc_url( $loading_image ) . '" /></p>' );
}
/**
* Called by javascript to process each image in the queue.
*/
function ewww_image_optimizer_webp_loop() {
ewwwio_debug_message( '<b>' . __FUNCTION__ . '()</b>' );
$permissions = apply_filters( 'ewww_image_optimizer_admin_permissions', '' );
if ( empty( $_REQUEST['ewww_wpnonce'] ) || ! wp_verify_nonce( sanitize_key( $_REQUEST['ewww_wpnonce'] ), 'ewww-image-optimizer-webp' ) || ! current_user_can( $permissions ) ) {
ewwwio_ob_clean();
die( wp_json_encode( array( 'error' => esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ) ) ) );
}
if ( empty( $_REQUEST['webp_images'] ) || ! is_array( $_REQUEST['webp_images'] ) ) {
ewwwio_ob_clean();
die( wp_json_encode( array( 'error' => esc_html__( 'No images to migrate.', 'ewww-image-optimizer' ) ) ) );
}
// Retrieve the time when the migration starts.
$started = microtime( true );
if ( ewww_image_optimizer_stl_check() ) {
set_time_limit( 0 );
}
ewwwio_debug_message( 'renaming images now' );
$images_processed = 0;
$images_renamed = 0;
$output = '';
$images = array_map( 'sanitize_text_field', wp_unslash( $_REQUEST['webp_images'] ) );
while ( $images ) {
++$images_processed;
ewwwio_debug_message( "processed $images_processed images so far" );
$image = array_pop( $images );
if ( ! ewwwio_is_file( $image ) ) {
ewwwio_debug_message( "skipping $image because it is not a file, or not in a permitted folder" );
continue;
}
$replace_base = '';
$skip = true;
$naming_mode = ewww_image_optimizer_get_option( 'ewww_image_optimizer_webp_naming_mode', 'append' );
$extensionless = ewwwio()->remove_from_end( $image, '.webp' );
$info = pathinfo( $extensionless );
$ext = strtolower( $info['extension'] ?? '' );
$original_extensions = array( 'png', 'jpg', 'jpeg', 'gif' );
$is_real_ext = in_array( $ext, $original_extensions, true );
if ( 'replace' === $naming_mode ) {
if ( $is_real_ext && ewwwio_is_file( $extensionless ) ) {
$replace_base = $extensionless;
$skip = false;
}
} elseif ( 'append' === $naming_mode ) {
if ( $is_real_ext ) {
continue;
}
foreach ( $original_extensions as $img_ext ) {
if ( ewwwio_is_file( $extensionless . '.' . $img_ext ) || ewwwio_is_file( $extensionless . '.' . strtoupper( $img_ext ) ) ) {
if ( ! empty( $replace_base ) ) {
$skip = true;
break;
}
$replace_base = $extensionless . '.' . $img_ext;
$skip = false;
}
}
}
if ( $skip ) {
if ( $replace_base ) {
ewwwio_debug_message( "multiple replacement options for $image, not renaming" );
} else {
ewwwio_debug_message( "no match found for $image, strange..." );
}
/* translators: %s: a webp file */
$output .= sprintf( esc_html__( 'Skipped %s, could not determine original image path', 'ewww-image-optimizer' ), esc_html( $image ) ) . '<br>';
} else {
$new_webp_path = ewww_image_optimizer_get_webp_path( $replace_base );
if ( is_file( $new_webp_path ) ) {
ewwwio_debug_message( "$new_webp_path already exists, deleting $image" );
ewwwio_delete_file( $image );
/* translators: 1: a webp file 2: another webp file */
$output .= sprintf( esc_html__( '%1$s already exists, removed %2$s', 'ewww-image-optimizer' ), esc_html( $new_webp_path ), esc_html( $image ) ) . '<br>';
continue;
}
++$images_renamed;
ewwwio_debug_message( "renaming $image with match of $replace_base to $new_webp_path" );
rename( $image, $new_webp_path );
}
} // End while().
if ( $images_renamed ) {
/* translators: %d: number of images */
$output .= sprintf( esc_html__( 'Renamed %d WebP images', 'ewww-image-optimizer' ), (int) $images_renamed ) . '<br>';
}
// Calculate how much time has elapsed since we started.
$elapsed = microtime( true ) - $started;
ewwwio_debug_message( "took $elapsed seconds this time around" );
// Store the updated list of images back in the database.
echo wp_json_encode(
array(
'output' => $output,
)
);
die();
}
/**
* Called by javascript to cleanup after ourselves.
*/
function ewww_image_optimizer_webp_cleanup() {
$permissions = apply_filters( 'ewww_image_optimizer_admin_permissions', '' );
if ( empty( $_REQUEST['ewww_wpnonce'] ) || ! wp_verify_nonce( sanitize_key( $_REQUEST['ewww_wpnonce'] ), 'ewww-image-optimizer-webp' ) || ! current_user_can( $permissions ) ) {
ewwwio_ob_clean();
die( esc_html__( 'Access token has expired, please reload the page.', 'ewww-image-optimizer' ) );
}
ewwwio_ob_clean();
// and let the user know we are done.
die( '<p><b>' . esc_html__( 'Finished', 'ewww-image-optimizer' ) . '</b></p>' );
}
add_action( 'admin_enqueue_scripts', 'ewww_image_optimizer_webp_script' );
add_action( 'wp_ajax_webp_init', 'ewww_image_optimizer_webp_initialize' );
add_action( 'wp_ajax_webp_loop', 'ewww_image_optimizer_webp_loop' );
add_action( 'wp_ajax_webp_cleanup', 'ewww_image_optimizer_webp_cleanup' );