Skip to content

Instantly share code, notes, and snippets.

@stracker-phil
Forked from divimode-philipp/asset-cache.php
Created September 30, 2022 08:33

Revisions

  1. @divimode-philipp divimode-philipp created this gist Sep 20, 2022.
    74 changes: 74 additions & 0 deletions asset-cache.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,74 @@
    <?php
    /**
    * Proof of concept for https://github.com/divimode/gdpr-cache-script-styles
    */


    /**
    * Filter all scripts and style URLs.
    * When an external URL is detected, download the file
    * and replace it in the page source.
    */
    add_filter( 'scripts_loader_src', 'maybe_replace_url' );
    add_filter( 'style_loader_src', 'maybe_replace_url' );

    /**
    * Takes any URL as input, and always returns a local
    * URL.
    *
    * If an external URL is provided, the external asset
    * is downloaded to the uploads-folder and the function
    * return value is a URL to that local file.
    */
    function maybe_replace_url( $url ) {
    if ( is_external_url( $url ) ) {
    if ( cache_asset( $url ) ) {
    $url = WP_CONTENT_URL .
    '/uploads/gdpr-cache/' .
    md5( $url );
    }
    }

    return $url;
    }

    /**
    * Returns true, if the specified URL points to an external asset.
    */
    function is_external_url( string $url ) : bool {
    // Relative URLs are always local to the current domain.
    if ( 0 === strpos( $url, '/' ) ) {
    return false;
    }

    // Get protocol-relative
    $home_url = preg_replace( '/^\w+:/', '', home_url() );

    return false === strpos( $url, $home_url );
    }

    /**
    * Downloads the given URL to the websites uploads-folder.
    * Returns true on success.
    */
    function cache_asset( $url ) {
    $cache_dir = WP_CONTENT_DIR . '/uploads/gdpr-cache/';
    $cache_path = $cache_dir . md5( $url );

    $resp = wp_safe_remote_get(
    $url,
    [
    'timeout' => 300,
    'stream' => true,
    'filename' => $cache_path,
    ]
    );

    if ( is_wp_error( $resp ) ) {
    @unlink( $cache_path );

    return false;
    }

    return true;
    }