PluginProbe
WP Super Minify • Minify, Compress and Cache HTML, CSS & JavaScript / trunk
WP Super Minify • Minify, Compress and Cache HTML, CSS & JavaScript vtrunk
trunk 1.0 1.1 1.2 1.3 1.3.1 1.3.2 1.4 1.5 1.5.1 1.6 2.0 2.0.1
wp-super-minify / wp-super-minify.php

wp-super-minify.php in WP Super Minify • Minify, Compress and Cache HTML, CSS & JavaScript trunk, at wp-super-minify.php

406 lines 16.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 Plugin Name: WP Super Minify
4 Plugin URI: https://github.com/dipakcg/wp-super-minify
5 Description: Smartly minify, compress and cache HTML, CSS & JavaScript files to boost website speed. 🚀
6 Version: 2.0.1
7 Author: Dipak C. Gajjar
8 Author URI: https://dipakgajjar.com
9 */
10
11 // Define plugin version for future releases
12 if ( !defined ('WPSMY_PLUGIN_VERSION_NUM' ) ) {
13 define( 'WPSMY_PLUGIN_VERSION_NUM', '2.0.1' );
14 }
15 if ( !defined ('WPSMY_MINIFY_LIBRARY_PATH' ) ) {
16 define( 'WPSMY_MINIFY_LIBRARY_PATH', plugin_dir_path( __FILE__ ) . 'includes/min' );
17 }
18 if ( !defined ('WPSMY_CACHE_DIR' ) ) {
19 define( 'WPSMY_CACHE_DIR', WP_CONTENT_DIR . '/cache/wp-super-minify/' );
20 }
21 if ( !defined ('WPSMY_CSS_CACHE_DIR' ) ) {
22 define( 'WPSMY_CSS_CACHE_DIR', WPSMY_CACHE_DIR . 'css/' );
23 }
24 if ( !defined ('WPSMY_JS_CACHE_DIR' ) ) {
25 define( 'WPSMY_JS_CACHE_DIR', WPSMY_CACHE_DIR . 'js/' );
26 }
27
28 require_once( plugin_dir_path( __FILE__ ) . 'clear-minified-cache.php' );
29 require_once( plugin_dir_path( __FILE__ ) . 'rating-support.php' );
30
31 // require_once( WPSMY_MINIFY_LIBRARY_PATH . "/src/" . strtoupper($type) . '.php' );
32 require_once( WPSMY_MINIFY_LIBRARY_PATH . "/src/Minify.php" );
33 require_once( WPSMY_MINIFY_LIBRARY_PATH . "/src/CSS.php" );
34 require_once( WPSMY_MINIFY_LIBRARY_PATH . "/src/JS.php" );
35 require_once( WPSMY_MINIFY_LIBRARY_PATH . "/../path-converter/ConverterInterface.php" );
36 require_once( WPSMY_MINIFY_LIBRARY_PATH . '/../path-converter/Converter.php' );
37
38 // Create Cache directories and sub-directories for CSS and JS
39 if ( !file_exists( WPSMY_CACHE_DIR ) ) mkdir( WPSMY_CACHE_DIR, 0755, true );
40 if ( !file_exists( WPSMY_CSS_CACHE_DIR ) ) mkdir( WPSMY_CSS_CACHE_DIR, 0755, true );
41 if ( !file_exists( WPSMY_JS_CACHE_DIR ) ) mkdir( WPSMY_JS_CACHE_DIR, 0755, true );
42
43 // Register with hook 'wp_enqueue_scripts', which can be used for front end CSS and JavaScript
44 add_action( 'admin_init', 'wpsmy_add_stylesheet' );
45 function wpsmy_add_stylesheet() {
46 // Respects SSL, Style.css is relative to the current file
47 wp_register_style( 'wpsmy-stylesheet', plugins_url('assets/css/style.min.css', __FILE__) );
48 wp_enqueue_style( 'wpsmy-stylesheet' );
49
50 // Hook 'Review this plugin'
51 do_action( 'wpsmy_rating_system_action' );
52 }
53
54 // Register admin menu
55 add_action( 'admin_menu', 'wpsmy_add_admin_menu' );
56 function wpsmy_add_admin_menu() {
57 // add_menu_page( 'WP Super Minify Settings', 'WP Super Minify', 'manage_options', 'wp-super-minify', 'wpsmy_admin_options', plugins_url('assets/images/wpsmy-icon-24x24.png', __FILE__) );
58 // add_options_page( $page_title, $menu_title, $capability, $menu_slug, $function);
59 add_options_page( 'WP Super Minify', 'WP Super Minify', 'manage_options', 'wp-super-minify', 'wpsmy_admin_options' );
60 }
61
62 // Add settings link on plugin page
63 function wpsmy_settings_link( $links ) {
64 // $settings_link = '<a href="admin.php?page=wp-performance-score-booster">Settings</a>';
65 $settings_link = '<a href="options-general.php?page=wp-super-minify">Settings</a>';
66 array_unshift($links, $settings_link);
67 return $links;
68 }
69 $plugin = plugin_basename( __FILE__ );
70 add_filter( "plugin_action_links_$plugin", 'wpsmy_settings_link' );
71
72 // Adding WordPress plugin meta links
73 function wpsmy_plugin_meta_links( $links, $file ) {
74 $plugin = plugin_basename( __FILE__ );
75 // Create link
76 if ( $file == $plugin ) {
77 return array_merge(
78 $links,
79 array( '<a href="https://dipakgajjar.com/products/wordpress-speed-optimisation-service?utm_source=plugins%20page&utm_medium=text%20link&utm_campaign=wordplress%20plugins" style="color:#FF0000;" target="_blank">Order Pro-Level WordPress Speed Optimisation Services</a>' )
80 );
81 }
82 return $links;
83 }
84 add_filter( 'plugin_row_meta', 'wpsmy_plugin_meta_links', 10, 2 );
85
86 // Admin options/setting page
87 function wpsmy_admin_options() {
88 ?>
89 <div class="wrap">
90 <table width="100%" border="0">
91 <tr>
92 <td width="75%">
93 <h2>
94 <img src="<?php echo plugins_url( 'assets/images/wpsmy-icon-24x24.png', __FILE__ ); ?>"
95 style="vertical-align: middle; width="24" height="24">
96 WP Super Minify : Settings
97 </h2>
98 <hr />
99 <?php
100 if ( !current_user_can( 'manage_options' ) ) {
101 wp_die( __('You do not have sufficient permissions to access this page.') );
102 }
103
104 // Variables for the field and option names
105 $hidden_field_name = 'wpsmy_submit_hidden';
106 $combine_js = 'wpsmy_combine_js';
107 $combine_css = 'wpsmy_combine_css';
108
109 // Read in existing option value from database
110 $combine_js_val = get_option($combine_js);
111 $combine_css_val = get_option($combine_css);
112
113 // See if the user has posted us some information
114 // If they did, this hidden field will be set to 'Y'
115 if( isset( $_POST[$hidden_field_name] ) && $_POST[$hidden_field_name] == 'Y' ) {
116 // CSRF Check
117 if ( isset( $_REQUEST['_wpnonce'] ) && wp_verify_nonce( $_REQUEST['_wpnonce'], 'wpsmy_settings_nonce' ) ) {
118 if ( isset( $_POST['wpsmy_clear_minified'] ) ) {
119 wpsmy_clear_minified_cache();
120 }
121 else {
122 // Read their posted value
123 $combine_js_val = ( isset( $_POST[$combine_js] ) ? sanitize_text_field( $_POST[$combine_js] ) : "" );
124 $combine_css_val = ( isset( $_POST[$combine_css] ) ? sanitize_text_field( $_POST[$combine_css] ) : "" );
125
126 // Save the posted value in the database
127 update_option( $combine_js, $combine_js_val );
128 update_option( $combine_css, $combine_css_val );
129
130 echo '<div class="updated"><p><strong>Settings Saved.</strong></p></div>';
131 }
132 }
133 }
134 ?>
135 <form method="post" name="options_form">
136 <?php wp_nonce_field( 'wpsmy_settings_nonce' ); ?>
137 <input type="hidden" name="<?php echo $hidden_field_name; ?>" value="Y">
138 <p>
139 <input type="checkbox" name="<?php echo $combine_css; ?>" id="<?php echo $combine_css; ?>" <?php checked( $combine_css_val == 'on',true); ?> />
140 <label for="<?php echo $combine_css; ?>" class="wpsmy_settings" style="display: inline;"> <?php _e('Optimise CSS'); ?> </label>
141 </p>
142 <p>
143 <input type="checkbox" name="<?php echo $combine_js; ?>" id="<?php echo $combine_js; ?>" <?php checked( $combine_js_val == 'on',true); ?> />
144 <label for="<?php echo $combine_js; ?>" class="wpsmy_settings" style="display: inline;"> <?php _e('Optimise JavaScript'); ?> </label>
145 </p>
146 <p><input type="submit" value="<?php esc_attr_e('Save Changes') ?>" class="button button-primary" name="submit" />
147 <button type="submit" name="wpsmy_clear_minified" class="button button-primary">Clear CSS & JS Cache</button>
148 </p>
149 </form>
150 <p> &nbsp; </p>
151 <?php
152 $message = "";
153 $css_enabled = ($combine_css_val == 'on');
154 $js_enabled = ($combine_js_val == 'on');
155
156 $templates = [
157 'css_js' => "�
158 WP Super Minify now minifies, compresses, and caches all %s files. Enable '<em>Optimise %s</em>' to further boost your site's performance.",
159 'both' => "�
160 WP Super Minify now minifies, compresses, and caches all CSS & JavaScript files making your site lighter, faster, and more optimised than ever! 🚀",
161 'none' => "<span style='color: RED !important;'> You haven’t selected any options above WP Super Minify isn’t currently optimising your site.
162 <br /> <br />If you’re not debugging or troubleshooting errors, consider enabling the options above to boost your site's performance.</span>",
163 ];
164 $hassle_free_updates = "�
165 Enjoy a seamless experience — Minified files are automatically updated whenever the original files are modified.";
166
167 if ( $js_enabled && !$css_enabled ) {
168 $message = sprintf($templates['css_js'], "JavaScript", "CSS") . '<br /> <br />' . $hassle_free_updates;
169 } elseif ( $css_enabled && !$js_enabled ) {
170 $message = sprintf($templates['css_js'], "CSS", "JS") . '<br /> <br />' . $hassle_free_updates;
171 } elseif ( $js_enabled && $css_enabled ) {
172 $message = $templates['both'] . '<br /> <br />' . $hassle_free_updates;
173 } else {
174 $message = $templates['none'];
175 }
176 // Output the final message
177 echo '<p style="color:#00a32a; font-weight: bold;">' . $message . '</p>';
178 ?>
179 </td>
180 <td style="text-align: left;">
181 <div class="wpsmy_admin_dev_sidebar_div">
182 <!-- <img src="//www.gravatar.com/avatar/38b380cf488d8f8c4007cf2015dc16ac.jpg" width="100px" height="100px" /> -->
183 <br />
184 <span class="wpsmy_admin_dev_sidebar"> <?php echo '<img src="' . plugins_url( 'assets/images/wpsmy-support-this-16x16.png' , __FILE__ ) . '" > '; ?> <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=3S8BRPLWLNQ38" target="_blank"> Donate and support this plugin </a> </span>
185 <span class="wpsmy_admin_dev_sidebar"> <?php echo '<img src="' . plugins_url( 'assets/images/wpsmy-rate-this-16x16.png' , __FILE__ ) . '" > '; ?> <a href="http://wordpress.org/support/view/plugin-reviews/wp-super-minify" target="_blank"> Rate this plugin on WordPress.org </a> </span>
186 <span class="wpsmy_admin_dev_sidebar"> <?php echo '<img src="' . plugins_url( 'assets/images/wpsmy-wordpress-16x16.png' , __FILE__ ) . '" > '; ?> <a href="http://wordpress.org/support/plugin/wp-super-minify" target="_blank"> Get support on WordPress.org </a> </span>
187 <span class="wpsmy_admin_dev_sidebar"> <?php echo '<img src="' . plugins_url( 'assets/images/wpsmy-github-16x16.png' , __FILE__ ) . '" > '; ?> <a href="https://github.com/dipakcg/wp-super-minify" target="_blank"> Contribute development on GitHub </a> </span>
188 <span class="wpsmy_admin_dev_sidebar"> <?php echo '<img src="' . plugins_url( 'assets/images/wpsmy-other-plugins-16x16.png' , __FILE__ ) . '" > '; ?> <a href="http://profiles.wordpress.org/dipakcg#content-plugins" target="_blank"> Get my other plugins </a> </span>
189 <span class="wpsmy_admin_dev_sidebar"> <?php echo '<img src="' . plugins_url( 'assets/images/wpsmy-twitter-16x16.png' , __FILE__ ) . '" > '; ?>Follow me on Twitter: <a href="https://twitter.com/dipakcgajjar" target="_blank">@dipakcgajjar</a> </span>
190 <br />
191 <span class="wpsmy_admin_dev_sidebar" style="float: right;"> Version: <strong> <?php echo get_option('wpsmy_plugin_version'); ?> </strong> </span>
192 </div>
193 </td>
194 </tr>
195 </table>
196 </div>
197 <?php
198 }
199
200 // Check if the plugin has been updated and display a review notice if applicable.
201 function wpsmy_check_plugin_update() {
202 $saved_version = get_option('wpsmy_plugin_version' ); // Default version if not set
203
204 /* Display review plugin notice if plugin updated */
205 // only applies to older versions of the plugin (older than 2.0.1) where option isn't set
206 // As version 2.0 is a major release, let's ask users to submit review on wordpress.org
207 if ( version_compare( $saved_version, WPSMY_PLUGIN_VERSION_NUM, '<' ) || $saved_version === FALSE ) {
208 // Version is less than 2.0.1, show the review notice
209 if ( $saved_version && in_array( $saved_version, ['2.0', '1.6'], true ) ) {
210 update_option( 'wpsmy_review_notice', 'on' );
211 }
212
213 // Update the version in the database to prevent repeated notices
214 update_option( 'wpsmy_plugin_version', WPSMY_PLUGIN_VERSION_NUM );
215 }
216 }
217 add_action( 'admin_init', 'wpsmy_check_plugin_update' );
218
219 // Make the default value of enable javascript and enable CSS to true on plugin activation
220 function wpsmy_activate_plugin() {
221
222 // Save default options value in the database
223 update_option( 'wpsmy_combine_js', 'on' );
224 update_option( 'wpsmy_combine_css', 'on' );
225
226 // Rate this plugin on wordpress.org - check for admin notice dismissal
227 if ( FALSE === get_option( 'wpsmy_review_notice' ) ) {
228 add_option( 'wpsmy_review_notice', 'on' );
229 }
230 }
231 register_activation_hook( __FILE__, 'wpsmy_activate_plugin' );
232
233 // Remove filters/functions on plugin deactivation
234 function wpsmy_deactivate_plugin() {
235 delete_option( 'wpsmy_plugin_version' );
236 }
237 register_deactivation_hook( __FILE__, 'wpsmy_deactivate_plugin' );
238
239 function wpsmy_minify_html( $buffer ) {
240 $wpsmy_plugin_version = get_option( 'wpsmy_plugin_version' );
241 $initial = strlen( $buffer );
242
243 // Include Minify libraries only if not already loaded
244 if ( !class_exists( 'Minify_HTML' ) ) {
245 require_once( WPSMY_MINIFY_LIBRARY_PATH . "/lib/Minify/HTML.php" );
246 require_once( WPSMY_MINIFY_LIBRARY_PATH . "/lib/Minify/Loader.php" );
247 Minify_Loader::register();
248 }
249
250 // Minify inline JavaScript if enabled
251 if ( get_option('wpsmy_combine_js', 1 ) === 'on') {
252 $buffer = Minify_HTML::minify( $buffer, array(
253 'jsMinifier' => array( 'JSMin', 'minify' )
254 ));
255 }
256
257 // Minify inline CSS if enabled
258 if (get_option( 'wpsmy_combine_css', 1 ) === 'on') {
259 $buffer = Minify_HTML::minify( $buffer, array(
260 'cssMinifier' => array( 'Minify_CSS', 'minify' )
261 ));
262 }
263
264 // Calculate savings
265 $final = strlen( $buffer );
266 if ($initial > 0) {
267 $savings = round((($initial - $final) / $initial * 100), 3);
268 } else {
269 $savings = 0; // Avoid division by zero
270 }
271
272 // Store the comment in a global variable instead of appending to the buffer
273 if ( $savings > 0 ) {
274 global $wpsmy_minify_comment;
275 $wpsmy_minify_comment = PHP_EOL . '<!--' . PHP_EOL .
276 '*** This site runs WP Super Minify plugin v' . esc_html($wpsmy_plugin_version) . ' - http://wordpress.org/plugins/wp-super-minify ***' . PHP_EOL .
277 '*** Total size saved: ' . esc_html($savings) . '% | Size before compression: ' . esc_html($initial) . ' bytes | Size after compression: ' . esc_html($final) . ' bytes. ***' . PHP_EOL .
278 '-->';
279 }
280
281 return $buffer;
282 }
283
284 // Start HTML Minification with output buffering
285 function wpsmy_html_minify_start() {
286 if (!is_admin() && !defined('DOING_AJAX')) {
287 ob_start('wpsmy_minify_html');
288 }
289 }
290 add_action( 'template_redirect', 'wpsmy_html_minify_start', 1 );
291
292 // Flush the buffer at the end of the page
293 function wpsmy_html_minify_end() {
294 if (!is_admin() && ob_get_length()) {
295 ob_end_flush();
296 }
297 }
298 add_action( 'shutdown', 'wpsmy_html_minify_end', 9999 );
299
300 // Output minification comment at the bottom of the page
301 function wpsmy_print_minify_comment() {
302 global $wpsmy_minify_comment;
303 if (!empty($wpsmy_minify_comment)) {
304 echo $wpsmy_minify_comment;
305 }
306 }
307 add_action( 'shutdown', 'wpsmy_print_minify_comment', 10000 );
308
309 // Hook to process and replace scripts and styles
310 add_action( 'wp_enqueue_scripts', 'wpsmy_minify_enqueue_scripts', 999 );
311 function wpsmy_minify_enqueue_scripts() {
312 global $wp_styles, $wp_scripts;
313
314 // Minify and replace styles
315 if ( !empty( $wp_styles->queue ) && get_option( 'wpsmy_combine_css', 1 ) === 'on' ) {
316 foreach ($wp_styles->queue as $handle) {
317 $src = $wp_styles->registered[$handle]->src;
318 if ($src) {
319 $minified_src = wpsmy_minify_file($src, 'css');
320 if ($minified_src) {
321 $wp_styles->registered[$handle]->src = $minified_src;
322 }
323 }
324 }
325 }
326
327 // Minify and replace scripts
328 if ( !empty( $wp_scripts->queue ) && get_option( 'wpsmy_combine_js', 1 ) === 'on' ) {
329 foreach ($wp_scripts->queue as $handle) {
330 $src = $wp_scripts->registered[$handle]->src;
331 if ($src) {
332 $minified_src = wpsmy_minify_file($src, 'js');
333 if ($minified_src) {
334 $wp_scripts->registered[$handle]->src = $minified_src;
335 }
336 }
337 }
338 }
339 }
340
341 /**
342 * Minifies a given CSS or JS file and stores it.
343 *
344 * @param string $file_url URL of the original file.
345 * @param string $type 'css' or 'js'.
346 * @return string|false Minified file URL or false if failed.
347 */
348 function wpsmy_minify_file( $file_url, $type ) {
349
350 if ( strpos($file_url, '.min.') !== false ) {
351 return $file_url; // Skip if already minified
352 }
353
354 $cache_filetype_dir = ( $type === 'js' ? 'js/' : 'css/' );
355 $cache_url = content_url() . '/cache/wp-super-minify/';
356
357 $file_path = str_replace(home_url(), ABSPATH, $file_url);
358 $minified_file_name = md5($file_url) . '.' . $type;
359 $minified_file_path = WPSMY_CACHE_DIR . $cache_filetype_dir . $minified_file_name;
360 $minified_file_url = $cache_url . $cache_filetype_dir . $minified_file_name;
361 $hash_file_path = $minified_file_path . '.hash'; // Store file hash
362
363 // Check if original file exists
364 if ( !file_exists( $file_path ) ) {
365 return false; // Skip if file is not local
366 }
367
368 // Get current file hash
369 $current_hash = md5_file($file_path);
370
371 // Check if minified file exists and hash matches
372 if ( file_exists($minified_file_path) && file_exists($hash_file_path) ) {
373 $saved_hash = file_get_contents( $hash_file_path );
374 if ( $saved_hash === $current_hash ) {
375 return $minified_file_url; // Return existing minified file
376 }
377 }
378
379 try {
380 if ( $type === 'css' ) {
381 $minifier = new MatthiasMullie\Minify\CSS( $file_path );
382 } elseif ( $type === 'js' ) {
383 $minifier = new MatthiasMullie\Minify\JS( $file_path );
384 } else {
385 return false;
386 }
387
388 $minifier->minify( $minified_file_path );
389
390 // Store hash to track changes
391 file_put_contents($hash_file_path, $current_hash);
392
393 // Store in options table
394 $stored_files = get_option( 'wpsmy_minified_files', [] );
395 $stored_files[$file_url] = $minified_file_url;
396 update_option( 'wpsmy_minified_files', $stored_files );
397
398 return $minified_file_url;
399 } catch ( Exception $e ) {
400 return false;
401 }
402 }
403
404 /* END OF PLUGIN */
405 ?>
406