Plugin Directory


Ignore:
Timestamp:
09/21/2022 03:04:24 PM (4 years ago)
Author:
stracker.phil
Message:

1.0.1

Location:
gdpr-cache-scripts-styles
Files:
17 added
9 edited

Legend:

Unmodified
Added
Removed
  • gdpr-cache-scripts-styles/trunk/constants.php

    r2785338 r2788227  
    3838 */
    3939const GDPR_CACHE_WORKER_LOCK = 'gdpr_lock';
     40
     41if ( ! 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  
    1616add_action( 'admin_init', __NAMESPACE__ . '\process_actions' );
    1717
    18 add_action( 'gdpr_cache_do_flush', __NAMESPACE__ . '\action_flush_cache' );
     18add_action( 'gdpr_cache_do_refresh', __NAMESPACE__ . '\action_refresh_cache' );
     19
     20add_action( 'gdpr_cache_do_purge', __NAMESPACE__ . '\action_purge_cache' );
    1921
    2022register_deactivation_hook( GDPR_CACHE_PLUGIN_FILE, __NAMESPACE__ . '\action_deactivate' );
     
    3032 */
    3133function process_actions() {
    32     if ( empty( $_POST['action'] ) || empty( $_POST['_wpnonce'] ) ) {
     34    if ( empty( $_REQUEST['action'] ) || empty( $_REQUEST['_wpnonce'] ) ) {
    3335        return;
    3436    }
    3537
    36     $action = sanitize_key( wp_unslash( $_POST['action'] ) );
     38    $action = sanitize_key( wp_unslash( $_REQUEST['action'] ) );
    3739
    3840    if ( 0 !== strpos( $action, 'gdpr-cache-' ) ) {
     
    4345    $gdpr_action = substr( $action, 11 );
    4446
    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 ) ) {
    4648        return;
    4749    }
     
    5860
    5961/**
    60  * Renders the admin option-page of our plugin.
     62 * Initiates a cache-refresh and display a success message on the admin page.
    6163 *
    6264 * @since 1.0.0
    6365 * @return void
    6466 */
    65 function action_flush_cache() {
     67function action_refresh_cache() {
    6668    flush_cache( true );
    6769
    6870    $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 */
     87function action_purge_cache() {
     88    flush_cache();
     89
     90    $redirect_to = add_query_arg( [
     91        'update'   => 'purged',
    7092        '_wpnonce' => wp_create_nonce( 'gdpr-cache' ),
    7193    ] );
  • gdpr-cache-scripts-styles/trunk/includes/admin/options.php

    r2785338 r2788227  
    6262    }
    6363
    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' );
    6668    }
    6769}
     
    8082
    8183/**
    82  * Outputs an admin notice: Cache flushed.
     84 * Outputs an admin notice: Cache refreshed.
    8385 *
    8486 * @since 1.0.0
    8587 * @return void
    8688 */
    87 function admin_notice_flushed() {
     89function admin_notice_refreshed() {
    8890    printf(
    8991        '<div class="notice-%s notice is-dismissible"><p>%s</p></div>',
    9092        'success',
    91         esc_html__( 'Cache flushed', 'gdpr-cache' )
     93        esc_html__( 'Refreshing the cache in the background', 'gdpr-cache' )
    9294    );
    9395}
     96
     97
     98/**
     99 * Outputs an admin notice: Cache purged.
     100 *
     101 * @since 1.0.1
     102 * @return void
     103 */
     104function 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  
    240240    $timeout = 300;
    241241
    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;
    259257    $cache_path = build_cache_file_path( $filename );
    260258
     
    298296    return set_local_item( $url, $filename, $expires );
    299297}
     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 */
     310function 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  
    151151        $uri = trim( $matches[2], '"\'' );
    152152
    153         $type = get_url_type( $uri );
    154 
    155153        // Try to cache the external dependency.
    156         $local_uri = swap_to_local_asset( $uri, $type );
     154        $local_uri = swap_to_local_asset( $uri );
    157155
    158156        if ( $local_uri ) {
  • gdpr-cache-scripts-styles/trunk/includes/libs/utils.php

    r2785338 r2788227  
    116116        'image/gif'       => 'gif',
    117117    ];
    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     */
    120138    $path = wp_parse_url( $uri, PHP_URL_PATH );
    121139    if ( preg_match( '/\w+$/', $path, $matches ) ) {
    122140        $type = strtolower( $matches[0] );
    123         if ( array_key_exists( $type, $types ) ) {
     141        if ( in_array( $type, $types ) ) {
    124142            return $type;
    125143        }
    126144    }
    127145
    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     */
    129156    $resp         = wp_remote_head( $uri );
    130157    $content_type = wp_remote_retrieve_header( $resp, 'content-type' );
     
    132159    $content_type = strtolower( trim( array_shift( $content_type ) ) );
    133160
    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        }
    136184    }
    137185
     
    166214    return $gdpr_cache_fs;
    167215}
    168 
  • gdpr-cache-scripts-styles/trunk/plugin.php

    r2785338 r2788227  
    1212 * Plugin URI:  https://github.com/divimode/gdpr-cache-script-styles
    1313 * 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.0
     14 * Version:     1.0.1
    1515 * Author:      Divimode
    1616 * Author URI:  https://divimode.com/
     
    4646 * @var string
    4747 */
    48 const GDPR_CACHE_VERSION = '1.0.0';
     48const GDPR_CACHE_VERSION = '1.0.1';
    4949
    5050/**
  • gdpr-cache-scripts-styles/trunk/readme.txt

    r2785338 r2788227  
    11=== GDPR Cache Scripts & Styles ===
    2 Tags: gdpr, ccpa, privacy, asset cache
     2Tags: gdpr, ccpa, privacy, asset cache, script cache, style cache, embed google fonts, local google fonts
    33Requires at least: 5.8
    44Tested up to: 6.0.2
    55Requires PHP: 7.4
    6 Stable tag: 1.0.0
     6Stable tag: 1.0.1
    77License: GPL v2 or later
    88License URI: http://www.gnu.org/licenses/gpl-2.0.txt
    99
    10 Cache external scripts and styles, and serve them from your local website.
     10Greatly enhances privacy of your website by embedding external scripts and styles.
    1111
    1212== Description ==
     
    2222## How it works
    2323
     24> **Short**: External files are downloaded to your WordPress installation (into the uploads-folder) and then served from there.
     25
     26**More details**:
     27
    2428The 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.
    2529
     
    2731
    2832Heads-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
     36This plugin does not add any "output buffering" but scans the URLs which are enqueued via recommended WordPress functions.
     37
     38As a result, *GDPR Cache Scripts & Styles* has practically no performance impact on your response time, no matter how big your website is.
    2939
    3040## Background worker
     
    4454Automatic WordPress installer:
    4555
    46 1. Install the plugin from wordpress.org
     561. Install [the plugin from wordpress.org](https://wordpress.org/plugins/gdpr-cache-scripts-styles/)
    47572. Activate it.
    48583. Done! No configuration needed.
     
    5060From GitHub:
    5161
    52 1. Visit https://github.com/divimode/gdpr-cache-script-styles and download the repository zip file.
     621. Visit [github.com/divimode/gdpr-cache-script-styles](https://github.com/divimode/gdpr-cache-script-styles/) and download the repository zip file.
    53632. Open your wp-admin > Plugins > Add New page and upload that zip file
    54643. Activate the plugin.
     
    6777Unfortunately, no. Some scripts (such as Google Maps scripts) will load external assets that cannot be detected or cached by this plugin.
    6878
     79= I still see some requests to Google's Servers =
     80Common 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
     85Also, 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
    6987== Screenshots ==
    7088
     
    7593== Changelog ==
    7694
     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
    77104= 1.0.0 =
    78105
  • gdpr-cache-scripts-styles/trunk/templates/admin-options.php

    r2785338 r2788227  
    7474}
    7575
     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
    7685?>
    7786<div class="wrap">
     
    7988
    8089    <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' ); ?>
    8291    </p>
    8392
    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>
    88108        </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"/>
    106112
    107113    <h2><?php esc_html_e( 'Cached Assets', 'gdpr-cache' ); ?></h2>
     
    167173        font-weight: bold;
    168174    }
     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    }
    169200</style>
Note: See TracChangeset for help on using the changeset viewer.