Changeset 2788227 for gdpr-cache-scripts-styles
- Timestamp:
- 09/21/2022 03:04:24 PM (4 years ago)
- Location:
- gdpr-cache-scripts-styles
- Files:
-
- 17 added
- 9 edited
-
tags/1.0.1 (added)
-
tags/1.0.1/LICENSE (added)
-
tags/1.0.1/constants.php (added)
-
tags/1.0.1/includes (added)
-
tags/1.0.1/includes/admin (added)
-
tags/1.0.1/includes/admin/actions.php (added)
-
tags/1.0.1/includes/admin/options.php (added)
-
tags/1.0.1/includes/libs (added)
-
tags/1.0.1/includes/libs/cache.php (added)
-
tags/1.0.1/includes/libs/scanner.php (added)
-
tags/1.0.1/includes/libs/utils.php (added)
-
tags/1.0.1/includes/libs/worker.php (added)
-
tags/1.0.1/plugin.php (added)
-
tags/1.0.1/readme.txt (added)
-
tags/1.0.1/start.php (added)
-
tags/1.0.1/templates (added)
-
tags/1.0.1/templates/admin-options.php (added)
-
trunk/constants.php (modified) (1 diff)
-
trunk/includes/admin/actions.php (modified) (4 diffs)
-
trunk/includes/admin/options.php (modified) (2 diffs)
-
trunk/includes/libs/cache.php (modified) (2 diffs)
-
trunk/includes/libs/scanner.php (modified) (1 diff)
-
trunk/includes/libs/utils.php (modified) (3 diffs)
-
trunk/plugin.php (modified) (2 diffs)
-
trunk/readme.txt (modified) (7 diffs)
-
trunk/templates/admin-options.php (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
gdpr-cache-scripts-styles/trunk/constants.php
r2785338 r2788227 38 38 */ 39 39 const GDPR_CACHE_WORKER_LOCK = 'gdpr_lock'; 40 41 if ( ! defined( 'GDPR_CACHE_DEFAULT_UA' ) ) { 42 /** 43 * Defines the default user-agent that is sent to remote servers when 44 * downloading a file to the local cache. 45 * 46 * Set this to false or an empty string to not include a default 47 * user-agent with remote requests. 48 * 49 * Effect: The default UA below will instruct Google Fonts to use WOFF2 50 * files. If you need to support IE, define an empty UA, which results 51 * in TTF fonts being used. 52 * 53 * @see https://developers.google.com/fonts/docs/technical_considerations 54 * 55 * @since 1.0.1 56 * @var string 57 */ 58 define( 'GDPR_CACHE_DEFAULT_UA', 'Mozilla/5.0 AppleWebKit/537 Chrome/105' ); 59 } -
gdpr-cache-scripts-styles/trunk/includes/admin/actions.php
r2785338 r2788227 16 16 add_action( 'admin_init', __NAMESPACE__ . '\process_actions' ); 17 17 18 add_action( 'gdpr_cache_do_flush', __NAMESPACE__ . '\action_flush_cache' ); 18 add_action( 'gdpr_cache_do_refresh', __NAMESPACE__ . '\action_refresh_cache' ); 19 20 add_action( 'gdpr_cache_do_purge', __NAMESPACE__ . '\action_purge_cache' ); 19 21 20 22 register_deactivation_hook( GDPR_CACHE_PLUGIN_FILE, __NAMESPACE__ . '\action_deactivate' ); … … 30 32 */ 31 33 function process_actions() { 32 if ( empty( $_ POST['action'] ) || empty( $_POST['_wpnonce'] ) ) {34 if ( empty( $_REQUEST['action'] ) || empty( $_REQUEST['_wpnonce'] ) ) { 33 35 return; 34 36 } 35 37 36 $action = sanitize_key( wp_unslash( $_ POST['action'] ) );38 $action = sanitize_key( wp_unslash( $_REQUEST['action'] ) ); 37 39 38 40 if ( 0 !== strpos( $action, 'gdpr-cache-' ) ) { … … 43 45 $gdpr_action = substr( $action, 11 ); 44 46 45 if ( ! wp_verify_nonce( sanitize_key( wp_unslash( $_ POST['_wpnonce'] ) ), $gdpr_action ) ) {47 if ( ! wp_verify_nonce( sanitize_key( wp_unslash( $_REQUEST['_wpnonce'] ) ), $gdpr_action ) ) { 46 48 return; 47 49 } … … 58 60 59 61 /** 60 * Renders the admin option-page of our plugin.62 * Initiates a cache-refresh and display a success message on the admin page. 61 63 * 62 64 * @since 1.0.0 63 65 * @return void 64 66 */ 65 function action_ flush_cache() {67 function action_refresh_cache() { 66 68 flush_cache( true ); 67 69 68 70 $redirect_to = add_query_arg( [ 69 'update' => 'flushed', 71 'update' => 'refreshed', 72 '_wpnonce' => wp_create_nonce( 'gdpr-cache' ), 73 ] ); 74 75 wp_safe_redirect( $redirect_to ); 76 77 exit; 78 } 79 80 81 /** 82 * Purges the cache and display a success message on the admin page. 83 * 84 * @since 1.0.1 85 * @return void 86 */ 87 function action_purge_cache() { 88 flush_cache(); 89 90 $redirect_to = add_query_arg( [ 91 'update' => 'purged', 70 92 '_wpnonce' => wp_create_nonce( 'gdpr-cache' ), 71 93 ] ); -
gdpr-cache-scripts-styles/trunk/includes/admin/options.php
r2785338 r2788227 62 62 } 63 63 64 if ( 'flushed' === $notice ) { 65 add_action( 'admin_notices', __NAMESPACE__ . '\admin_notice_flushed' ); 64 if ( 'refreshed' === $notice ) { 65 add_action( 'admin_notices', __NAMESPACE__ . '\admin_notice_refreshed' ); 66 } elseif ( 'purged' === $notice ) { 67 add_action( 'admin_notices', __NAMESPACE__ . '\admin_notice_purged' ); 66 68 } 67 69 } … … 80 82 81 83 /** 82 * Outputs an admin notice: Cache flushed.84 * Outputs an admin notice: Cache refreshed. 83 85 * 84 86 * @since 1.0.0 85 87 * @return void 86 88 */ 87 function admin_notice_ flushed() {89 function admin_notice_refreshed() { 88 90 printf( 89 91 '<div class="notice-%s notice is-dismissible"><p>%s</p></div>', 90 92 'success', 91 esc_html__( ' Cache flushed', 'gdpr-cache' )93 esc_html__( 'Refreshing the cache in the background', 'gdpr-cache' ) 92 94 ); 93 95 } 96 97 98 /** 99 * Outputs an admin notice: Cache purged. 100 * 101 * @since 1.0.1 102 * @return void 103 */ 104 function admin_notice_purged() { 105 printf( 106 '<div class="notice-%s notice is-dismissible"><p>%s</p></div>', 107 'success', 108 esc_html__( 'Cache purged', 'gdpr-cache' ) 109 ); 110 } -
gdpr-cache-scripts-styles/trunk/includes/libs/cache.php
r2785338 r2788227 240 240 $timeout = 300; 241 241 242 $headers = []; 243 244 /** 245 * Some assets return different content based on user-agent, so this 246 * filter allows us to inject those details. 247 */ 248 // $headers = apply_filters( 249 // 'gdpr_cache_download_asset_headers', 250 // $headers, 251 // $url 252 // ); 253 // 254 // $key = md5( json_encode( $headers ) ); 255 256 $domain = wp_parse_url( $url, PHP_URL_HOST ); 257 $parts = [ $domain, md5( $url ), $type ]; 258 $filename = implode( '.', $parts ); 242 // Get HTTP request headers for requesting the remote file. 243 $headers = get_remote_request_headers( $url, $type ); 244 245 // Add a CRC32 key to generate a unique filename based on URL and headers. 246 $key = implode( ' ', [ $url, wp_json_encode( $headers ) ] ); 247 248 $extension = implode( '.', [ '', crc32( $key ), $type ] ); 249 250 // Create a normalized base-name that reflects the remote asset URI. 251 $base_name = substr( $url, strpos( $url, '//' ) + 2 ); 252 $base_name = preg_replace( '/\W+/', '.', $base_name ); 253 $base_name = substr( $base_name, 0, 250 - strlen( $extension ) ); 254 $base_name = strtolower( trim( $base_name, '.' ) ); 255 256 $filename = $base_name . $extension; 259 257 $cache_path = build_cache_file_path( $filename ); 260 258 … … 298 296 return set_local_item( $url, $filename, $expires ); 299 297 } 298 299 /** 300 * Returns an array with HTTP headers that should be used to request the 301 * specified asset from the remote server. 302 * 303 * @since 1.0.1 304 * 305 * @param string $url The external URL that will be requested. 306 * @param string $type File-type extension of the remote file. 307 * 308 * @return string[] List of headers that are passed to `wp_remote_get()`. 309 */ 310 function get_remote_request_headers( $url, $type ) { 311 $headers = []; 312 313 // Insert the default user agent, if it's not empty. 314 if ( GDPR_CACHE_DEFAULT_UA ) { 315 $headers['User-agent'] = GDPR_CACHE_DEFAULT_UA; 316 } 317 318 /** 319 * Some assets return different content based on user-agent, so this 320 * filter allows us to inject those details. 321 * 322 * @since 1.0.1 323 * 324 * @param array $headers The request headers. 325 * @param string $url The URL that's requested. 326 * @param string $type File type extension of the requested file. 327 */ 328 return (array) apply_filters( 329 'gdpr_cache_remote_request_headers', 330 $headers, 331 $url, 332 $type 333 ); 334 } -
gdpr-cache-scripts-styles/trunk/includes/libs/scanner.php
r2785338 r2788227 151 151 $uri = trim( $matches[2], '"\'' ); 152 152 153 $type = get_url_type( $uri );154 155 153 // Try to cache the external dependency. 156 $local_uri = swap_to_local_asset( $uri , $type);154 $local_uri = swap_to_local_asset( $uri ); 157 155 158 156 if ( $local_uri ) { -
gdpr-cache-scripts-styles/trunk/includes/libs/utils.php
r2785338 r2788227 116 116 'image/gif' => 'gif', 117 117 ]; 118 119 // First, analyze the URI and see if it ends with a valid type. 118 $sub_types = [ 119 'css' => 'css', 120 'javascript' => 'js', 121 'ecmascript' => 'js', 122 'ttf' => 'ttf', 123 'otf' => 'otf', 124 'woff' => 'woff', 125 'woff2' => 'woff2', 126 'jpeg' => 'jpg', 127 'jpg' => 'jpg', 128 'png' => 'png', 129 'gif' => 'gif', 130 ]; 131 132 /** 133 * First, analyze the URI and see if it ends with a valid type. 134 * 135 * Example: https://c0.wp.com/p/jetpack/11.3.1/css/jetpack.css 136 * Will return "css" 137 */ 120 138 $path = wp_parse_url( $uri, PHP_URL_PATH ); 121 139 if ( preg_match( '/\w+$/', $path, $matches ) ) { 122 140 $type = strtolower( $matches[0] ); 123 if ( array_key_exists( $type, $types ) ) {141 if ( in_array( $type, $types ) ) { 124 142 return $type; 125 143 } 126 144 } 127 145 128 // If the URI is not unique, then we'll ask for the content-type. 146 /** 147 * If the URI is not unique, then we'll ask for the content-type. 148 * 149 * Send a HEAD request to the remote site to find out the content-type 150 * which is used by the server. The HEAD request is very fast, because it 151 * does not send any body-details, only the response headers. 152 * 153 * Example: "content-type: text/css; charset=utf-8" condenses to "text/css" 154 * Will return "css" 155 */ 129 156 $resp = wp_remote_head( $uri ); 130 157 $content_type = wp_remote_retrieve_header( $resp, 'content-type' ); … … 132 159 $content_type = strtolower( trim( array_shift( $content_type ) ) ); 133 160 134 if ( array_key_exists( $content_type, $content_types ) ) { 135 return $content_types[ $content_type ]; 161 if ( $content_type ) { 162 if ( array_key_exists( $content_type, $content_types ) ) { 163 return $content_types[ $content_type ]; 164 } 165 166 /** 167 * No exact match, inspect only second part of the content-type. 168 * 169 * Now we'll split the content-type into two parts and investigate the 170 * second part. 171 * 172 * Some subtypes exist in multiple types, like "text/javascript" and 173 * "application/javascript". 174 * 175 * Example "application/javascript" is reduced to "javascript" 176 * Will return "js" 177 */ 178 $sub_type = explode( '/', $content_type ); 179 $sub_type = array_pop( $sub_type ); 180 181 if ( array_key_exists( $sub_type, $sub_types ) ) { 182 return $sub_types[ $sub_type ]; 183 } 136 184 } 137 185 … … 166 214 return $gdpr_cache_fs; 167 215 } 168 -
gdpr-cache-scripts-styles/trunk/plugin.php
r2785338 r2788227 12 12 * Plugin URI: https://github.com/divimode/gdpr-cache-script-styles 13 13 * Description: Caches external scripts and styles and serves them from your local website to make it more compliant with GDPR regulations 14 * Version: 1.0. 014 * Version: 1.0.1 15 15 * Author: Divimode 16 16 * Author URI: https://divimode.com/ … … 46 46 * @var string 47 47 */ 48 const GDPR_CACHE_VERSION = '1.0. 0';48 const GDPR_CACHE_VERSION = '1.0.1'; 49 49 50 50 /** -
gdpr-cache-scripts-styles/trunk/readme.txt
r2785338 r2788227 1 1 === GDPR Cache Scripts & Styles === 2 Tags: gdpr, ccpa, privacy, asset cache 2 Tags: gdpr, ccpa, privacy, asset cache, script cache, style cache, embed google fonts, local google fonts 3 3 Requires at least: 5.8 4 4 Tested up to: 6.0.2 5 5 Requires PHP: 7.4 6 Stable tag: 1.0. 06 Stable tag: 1.0.1 7 7 License: GPL v2 or later 8 8 License URI: http://www.gnu.org/licenses/gpl-2.0.txt 9 9 10 Cache external scripts and styles, and serve them from your local website.10 Greatly enhances privacy of your website by embedding external scripts and styles. 11 11 12 12 == Description == … … 22 22 ## How it works 23 23 24 > **Short**: External files are downloaded to your WordPress installation (into the uploads-folder) and then served from there. 25 26 **More details**: 27 24 28 The plugin scans every URL that is enqueued via `wp_enqueue_script()` and `wp_enqueue_style()`. When detecting external URL, that file is saved to your uploads-folder and served from there. 25 29 … … 27 31 28 32 Heads-up: For technical reasons, we cannot scan the contents of JS files for such dependencies - JS files can always inject external assets 33 34 ## No Output Buffer 35 36 This plugin does not add any "output buffering" but scans the URLs which are enqueued via recommended WordPress functions. 37 38 As a result, *GDPR Cache Scripts & Styles* has practically no performance impact on your response time, no matter how big your website is. 29 39 30 40 ## Background worker … … 44 54 Automatic WordPress installer: 45 55 46 1. Install the plugin from wordpress.org56 1. Install [the plugin from wordpress.org](https://wordpress.org/plugins/gdpr-cache-scripts-styles/) 47 57 2. Activate it. 48 58 3. Done! No configuration needed. … … 50 60 From GitHub: 51 61 52 1. Visit https://github.com/divimode/gdpr-cache-script-stylesand download the repository zip file.62 1. Visit [github.com/divimode/gdpr-cache-script-styles](https://github.com/divimode/gdpr-cache-script-styles/) and download the repository zip file. 53 63 2. Open your wp-admin > Plugins > Add New page and upload that zip file 54 64 3. Activate the plugin. … … 67 77 Unfortunately, no. Some scripts (such as Google Maps scripts) will load external assets that cannot be detected or cached by this plugin. 68 78 79 = I still see some requests to Google's Servers = 80 Common reasons are: 81 82 * Some scripts (like Google Maps) can dynamically load Google Fonts or other external resources. This cannot be prevented by this plugin. 83 * A browser plugin loads external assets on every request. Test the page in an Incognito/Private window 84 85 Also, some themes or performance plugins can embed the external resources in a way that our plugin cannot detect. If this is the case for you, please let us know. We might be able to adjust this plugin, or provide you with instructions on how to configure the plugin/theme to be compatible with *GDPR Cache Scripts & Styles*. 86 69 87 == Screenshots == 70 88 … … 75 93 == Changelog == 76 94 95 = 1.0.1 = 96 97 * New: A "Purge Cache" button to the plugin options page 98 * New: Include a User-Agent when requesting remote files, to fetch WOFF2 fonts from Google instead of large TTF files 99 * Fix: Correctly determine asset type from file extension to avoid "tmp" types 100 * Improve: Color coding of the cache-status on the plugin options page 101 * Improve: Local cache 1files reflect the entire remote URL, to add transparency over the file contents 102 * Improve: Fix some typos and remove unused code 103 77 104 = 1.0.0 = 78 105 -
gdpr-cache-scripts-styles/trunk/templates/admin-options.php
r2785338 r2788227 74 74 } 75 75 76 $action_refresh = wp_nonce_url( 77 add_query_arg( [ 'action' => 'gdpr-cache-refresh' ] ), 78 'refresh' 79 ); 80 $action_purge = wp_nonce_url( 81 add_query_arg( [ 'action' => 'gdpr-cache-purge' ] ), 82 'purge' 83 ); 84 76 85 ?> 77 86 <div class="wrap"> … … 79 88 80 89 <p> 81 <?php esc_html_e( ' Overview and manage your locally cached assets', 'gdpr-cache' ); ?>90 <?php esc_html_e( 'View and manage your locally cached assets', 'gdpr-cache' ); ?> 82 91 </p> 83 92 84 <form method="post"> 85 <h2><?php esc_html_e( 'Cache Control', 'gdpr-cache' ); ?></h2> 86 <p> 87 <?php esc_html_e( 'Invalidating the cache will expire all cached files. The plugin will start to download the latest version of all files on the next request. While the cache is regenerated, the expired files are served.', 'gdpr-cache' ); ?> 93 <h2><?php esc_html_e( 'Cache Control', 'gdpr-cache' ); ?></h2> 94 <p> 95 <?php esc_html_e( 'Refreshing the cache will start to download all external files in the background. While the cache is regenerated, the expired files are served.', 'gdpr-cache' ); ?> 96 </p> 97 <p> 98 <?php esc_html_e( 'Purging the cache will instantly delete all cached files, and begin to build a new cache. Until the initialization is finished, assets are loaded from the external sites.', 'gdpr-cache' ); ?> 99 </p> 100 <div class="gdpr-cache-reset"> 101 <p class="submit"> 102 <a href="<?php echo esc_url_raw( $action_refresh ) ?>" class="button-primary"> 103 <?php esc_html_e( 'Refresh Cache', 'gdpr-cache' ) ?> 104 </a> 105 <a href="<?php echo esc_url_raw( $action_purge ) ?>" class="button"> 106 <?php esc_html_e( 'Purge Cache', 'gdpr-cache' ) ?> 107 </a> 88 108 </p> 89 <p> 90 <?php esc_html_e( 'To complete delete the entire cache, you need to disable the plugin.', 'gdpr-cache' ); ?> 91 </p> 92 <div class="gdpr-cache-reset"> 93 <p class="submit"> 94 <input 95 type="submit" 96 name="submit" 97 id="submit" 98 class="button" 99 value="<?php esc_attr_e( 'Invalidate Cache', 'gdpr-cache' ) ?>" 100 > 101 </p> 102 </div> 103 <?php wp_nonce_field( 'flush' ); ?> 104 <input type="hidden" name="action" value="gdpr-cache-flush"/> 105 </form> 109 </div> 110 <?php wp_nonce_field( 'flush' ); ?> 111 <input type="hidden" name="action" value="gdpr-cache-flush"/> 106 112 107 113 <h2><?php esc_html_e( 'Cached Assets', 'gdpr-cache' ); ?></h2> … … 167 173 font-weight: bold; 168 174 } 175 176 .widefat .asset-status { 177 vertical-align: middle; 178 text-align: center; 179 } 180 181 .status-valid .asset-status { 182 background: #c8e6c940; 183 color: #005005; 184 } 185 186 .status-expired .asset-status { 187 background: #ffecb340; 188 color: #c56000; 189 } 190 191 .status-missing .asset-status { 192 background: #ffccbc40; 193 color: #9f0000; 194 } 195 196 .status-enqueued .asset-status { 197 background: #e1bee740; 198 color: #38006b; 199 } 169 200 </style>
Note: See TracChangeset
for help on using the changeset viewer.