Skip to content

Commit a97258a

Browse files
committed
*Rebuild cache system without using SQL
1 parent de59261 commit a97258a

File tree

1 file changed

+151
-33
lines changed

1 file changed

+151
-33
lines changed

includes/class-rocket-async-css.php

Lines changed: 151 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ class Rocket_Async_Css {
3333
* Plugin version
3434
*/
3535
const VERSION = '0.4.16';
36+
37+
/**
38+
* Plugin version
39+
*/
40+
const TRANSIENT_PREFIX = 'rocket_async_css_style_';
3641
/**
3742
* The current version of the plugin.
3843
*
@@ -363,25 +368,34 @@ public function process_css_buffer( $buffer ) {
363368
}
364369
// Check post cache
365370
$post_cache_id_hash = md5( serialize( $urls ) );
366-
$post_cache_id = 'wp_rocket_async_css_style_';
371+
$post_cache_id = array();
367372
if ( is_singular() ) {
368-
$post_cache_id .= 'post_' . get_the_ID();
373+
$post_cache_id [] = 'post_' . get_the_ID();
369374
} else if ( is_tag() || is_category() || is_tax() ) {
370-
$post_cache_id .= 'term_' . get_queried_object()->term_id;
375+
$post_cache_id [] = 'term_' . get_queried_object()->term_id;
371376
} else if ( is_author() ) {
372-
$post_cache_id .= 'author_' . get_the_author_meta( 'ID' );
377+
$post_cache_id [] = 'author_' . get_the_author_meta( 'ID' );
373378
} else {
374-
$post_cache_id .= 'url_';
379+
$post_cache_id [] = 'url_';
375380
$this->disable_relative_plugin_filters();
376381
$query = array();
377382
wp_parse_str( $query_string, $query );
378383
$url = add_query_arg( $query, site_url( $wp->request ) );
379384
$this->enable_relative_plugin_filters();
380-
$post_cache_id .= md5( $url );
385+
$post_cache_id [] = md5( $url );
386+
}
387+
$post_cache_id [] = $post_cache_id_hash;
388+
if ( is_user_logged_in() ) {
389+
$post_cache_id [] = wp_get_current_user()->roles[0];
390+
$post_cache_role_id = $post_cache_id;
391+
$post_cache_role = $this->get_cache_fragment( $post_cache_id );
392+
if ( ! empty( $post_cache_role ) ) {
393+
$post_cache = $post_cache_role;
394+
} else {
395+
$post_cache_id [] = get_current_user_id();
396+
$post_cache = $this->get_cache_fragment( $post_cache_id );
397+
}
381398
}
382-
$post_cache_id .= "_{$post_cache_id_hash}_";
383-
$post_cache_id .= get_current_user_id();
384-
$post_cache = get_transient( $post_cache_id );
385399
if ( ! empty( $post_cache ) ) {
386400
// Cached file is gone, we dont have cache
387401
if ( ! file_exists( $post_cache['filename'] ) ) {
@@ -432,9 +446,8 @@ public function process_css_buffer( $buffer ) {
432446
// Being remote is defined as not having our home url, not being relative and not being in the CDN list
433447
if ( 0 != strpos( $href, '/' ) && ( ( $url_parts['host'] != $domain && ! in_array( $url_parts['host'], $cdn_domains ) ) || 'css' != pathinfo( parse_url( $href, PHP_URL_PATH ), PATHINFO_EXTENSION ) ) ) {
434448
// Check item cache
435-
$item_cache_id = md5( $href );
436-
$item_cache_id = 'wp_rocket_async_css_style_' . $item_cache_id;
437-
$item_cache = get_transient( $item_cache_id );
449+
$item_cache_id = array( md5( $href ) );
450+
$item_cache = $this->get_cache_fragment( $item_cache_id );
438451
$css_part = '';
439452
// Only run if there is no item cache
440453
if ( empty( $item_cache ) ) {
@@ -453,7 +466,7 @@ public function process_css_buffer( $buffer ) {
453466
}
454467
} else {
455468
$css_part = $this->minify_remote_file( $href, $file['body'] );
456-
set_transient( $item_cache_id, $css_part, get_rocket_purge_cron_interval() );
469+
$this->update_cache_fragment( $item_cache_id, $css_part );
457470
}
458471
} else {
459472
$css_part = $item_cache;
@@ -466,9 +479,8 @@ public function process_css_buffer( $buffer ) {
466479
if ( 0 == strpos( $href, '/' ) ) {
467480
$href = $home . $href;
468481
}
469-
$item_cache_id = md5( $href );
470-
$item_cache_id = 'wp_rocket_async_css_style_' . $item_cache_id;
471-
$item_cache = get_transient( $item_cache_id );
482+
$item_cache_id = array( md5( $href ) );
483+
$item_cache = $this->get_cache_fragment( $item_cache_id );
472484
// Only run if there is no item cache
473485
if ( empty( $item_cache ) ) {
474486
// Break up url
@@ -501,7 +513,7 @@ public function process_css_buffer( $buffer ) {
501513
}
502514

503515
$data = $this->_minify_css( $data, array( 'prependRelativePath' => trailingslashit( dirname( $url_parts['path'] ) ) ) );
504-
set_transient( $item_cache_id, $data, get_rocket_purge_cron_interval() );
516+
$this->update_cache_fragment( $item_cache_id, $data );
505517
} else {
506518
$data = $item_cache;
507519
}
@@ -512,16 +524,15 @@ public function process_css_buffer( $buffer ) {
512524
}
513525
} else {
514526
// Check item cache
515-
$item_cache_id = md5( $tag->textContent );
516-
$item_cache_id = 'wp_rocket_async_css_style_' . $item_cache_id;
517-
$item_cache = get_transient( $item_cache_id );
527+
$item_cache_id = array( md5( $tag->textContent ) );
528+
$item_cache = $this->get_cache_fragment( $item_cache_id );
518529
// Only run if there is no item cache
519530
if ( empty( $item_cache ) ) {
520531
// Remove any conditional comments for IE that somehow was put in the style tag
521532
$css_part = preg_replace( '/(?:<!--)?\[if[^\]]*?\]>.*?<!\[endif\]-->/is', '', $tag->textContent );
522533
$css_part = $minify_inline_css ? $this->_minify_css( $css_part ) : $css_part;
523534
$css .= $css_part;
524-
set_transient( $item_cache_id, $css_part, get_rocket_purge_cron_interval() );
535+
$this->update_cache_fragment( $item_cache_id, $css_part );
525536
} else {
526537
$css .= $item_cache;
527538
}
@@ -536,7 +547,10 @@ public function process_css_buffer( $buffer ) {
536547
if ( ! empty( $css ) ) {
537548
rocket_put_content( $filename, $css );
538549
$href = get_rocket_cdn_url( set_url_scheme( str_replace( ABSPATH, trailingslashit( $home ), $filename ) ) );
539-
set_transient( $post_cache_id, compact( 'filename', 'href' ), get_rocket_purge_cron_interval() );
550+
if ( empty( $post_cache_role ) ) {
551+
$this->update_cache_fragment( $post_cache_role_id, compact( 'filename', 'href' ) );
552+
}
553+
$this->update_cache_fragment( $post_cache_id, compact( 'filename', 'href' ) );
540554
}
541555
} else {
542556
extract( $post_cache );
@@ -612,6 +626,14 @@ private function enable_relative_plugin_filters() {
612626
}
613627
}
614628

629+
protected function get_cache_fragment( $path ) {
630+
if ( ! in_array( 'cache', $path ) ) {
631+
array_unshift( $path, 'cache' );
632+
}
633+
634+
return get_transient( self::TRANSIENT_PREFIX . implode( '_', $path ) );
635+
}
636+
615637
public function minify_remote_file( $url, $css ) {
616638
add_filter( 'rocket_url_no_dots', '__return_false', PHP_INT_MAX );
617639
$css_part = $this->_minify_css( $css, array( 'prependRelativePath' => rocket_add_url_protocol( rocket_remove_url_protocol( trailingslashit( dirname( $url ) ) ) ) ), false );
@@ -696,6 +718,79 @@ private function _get_content( $file ) {
696718
return $direct_filesystem->get_contents( $file );
697719
}
698720

721+
protected function update_cache_fragment( $path, $value ) {
722+
if ( ! in_array( 'cache', $path ) ) {
723+
array_unshift( $path, 'cache' );
724+
}
725+
$this->build_cache_tree( array_slice( $path, 0, count( $path ) - 1 ) );
726+
$this->update_tree_branch( $path, $value );
727+
}
728+
729+
protected function build_cache_tree( $path ) {
730+
$levels = count( $path );
731+
$expire = get_rocket_purge_cron_interval();
732+
for ( $i = 0; $i < $levels; $i ++ ) {
733+
$transient_id = self::TRANSIENT_PREFIX . implode( '_', array_slice( $path, 0, $i + 1 ) );
734+
$transient_cache_id = $transient_id;
735+
if ( 'cache' != $path[ $i ] ) {
736+
$transient_cache_id .= '_cache';
737+
}
738+
$transient_cache_id .= '_1';
739+
$cache = get_transient( $transient_cache_id );
740+
$transient_value = array();
741+
if ( $i + 1 < $levels ) {
742+
$transient_value[] = self::TRANSIENT_PREFIX . implode( '_', array_slice( $path, 0, $i + 2 ) );
743+
}
744+
if ( ! is_null( $cache ) && false !== $cache ) {
745+
$transient_value = array_unique( array_merge( $cache, $transient_value ) );
746+
}
747+
set_transient( $transient_cache_id, $transient_value, $expire );
748+
$transient_counter_id = $transient_id;
749+
if ( 'cache' != $path[ $i ] ) {
750+
$transient_counter_id .= '_cache';
751+
}
752+
$transient_counter_id .= '_count';
753+
$transient_counter = get_transient( $transient_counter_id );
754+
if ( is_null( $transient_counter ) || false === $transient_counter ) {
755+
set_transient( $transient_counter_id, 1, $expire );
756+
}
757+
}
758+
}
759+
760+
protected function update_tree_branch( $path, $value ) {
761+
$branch = self::TRANSIENT_PREFIX . implode( '_', $path );
762+
$parent_path = array_slice( $path, 0, count( $path ) - 1 );
763+
$parent = self::TRANSIENT_PREFIX . implode( '_', $parent_path );
764+
$counter_transient = $parent;
765+
$cache_transient = $parent;
766+
if ( 'cache' != end( $parent_path ) ) {
767+
$counter_transient .= '_cache';
768+
$cache_transient .= '_cache';
769+
}
770+
$counter_transient .= '_count';
771+
$counter = (int) get_transient( $counter_transient );
772+
$cache_transient .= "_{$counter}";
773+
$cache = get_transient( $cache_transient );
774+
$count = count( $cache );
775+
$cache_keys = array_flip( $cache );
776+
$expire = get_rocket_purge_cron_interval();
777+
if ( ! isset( $cache_keys[ $branch ] ) ) {
778+
if ( $count >= apply_filters( 'rocket_async_css_max_branch_length', 50 ) ) {
779+
$counter ++;
780+
set_transient( $counter_transient, $counter, $expire );
781+
$cache_transient = $parent;
782+
if ( 'cache' != end( $parent_path ) ) {
783+
$cache_transient .= '_cache';
784+
}
785+
$cache_transient .= "_{$counter}";
786+
$cache = array();
787+
}
788+
$cache[] = $branch;
789+
set_transient( $cache_transient, $cache, $expire );
790+
}
791+
set_transient( $branch, $value, $expire );
792+
}
793+
699794
/**
700795
* Add conditional comments back in
701796
*
@@ -757,6 +852,7 @@ public function _activate_error_no_domdocument() {
757852

758853
/**
759854
* A hack to ensure rev slider runs on winsow load
855+
*
760856
* @return mixed
761857
*/
762858
public function rev_slider_compatibility() {
@@ -769,18 +865,43 @@ public function rev_slider_compatibility() {
769865
* Prune all css transients
770866
*/
771867
public function prune_transients() {
772-
global $wpdb;
773-
$wpdb->get_results( $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s", '_transient_wp_rocket_async_css_style_%', '_transient_timeout_wp_rocket_async_css_style_%' ) );
774-
wp_cache_flush();
868+
$this->delete_cache_branch();
869+
}
870+
871+
protected function delete_cache_branch( $path = array() ) {
872+
if ( is_array( $path ) ) {
873+
if ( ! empty( $path ) ) {
874+
$path = self::TRANSIENT_PREFIX . implode( '_', $path ) . '_';
875+
} else {
876+
$path = self::TRANSIENT_PREFIX;
877+
}
878+
}
879+
$counter_transient = "{$path}cache_count";
880+
$counter = get_transient( $counter_transient );
881+
882+
if ( is_null( $counter ) || false === $counter ) {
883+
delete_transient( rtrim( $path, '_' ) );
884+
885+
return;
886+
}
887+
for ( $i = 1; $i <= $counter; $i ++ ) {
888+
$transient_name = "{$path}cache_{$i}";
889+
$cache = get_transient( "{$path}cache_{$i}" );
890+
if ( ! empty( $cache ) ) {
891+
foreach ( $cache as $sub_branch ) {
892+
$this->delete_cache_branch( "{$sub_branch}_" );
893+
}
894+
delete_transient( $transient_name );
895+
}
896+
}
897+
delete_transient( $counter_transient );
775898
}
776899

777900
/**
778901
* Prune all css transients for a given term
779902
*/
780903
public function prune_term_transients( $term ) {
781-
global $wpdb;
782-
$wpdb->get_results( $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s", "_transient_wp_rocket_async_css_style_term_{$term->term_id}%", "_transient_timeout_wp_rocket_async_css_style_term_{$term->term_id}%" ) );
783-
wp_cache_flush();
904+
$this->delete_cache_branch( array( 'cache', "term_{$term->term_id}" ) );
784905
}
785906

786907
/**
@@ -813,16 +934,13 @@ public function prune_home_transients() {
813934
* Prune all css transients for a given post
814935
*/
815936
public function prune_post_transients( $post ) {
816-
global $wpdb;
817-
$wpdb->get_results( $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s", "_transient_wp_rocket_async_css_style_post_{$post->ID}%", "_transient_timeout_wp_rocket_async_css_style_post_{$post->ID}%" ) );
937+
$this->delete_cache_branch( array( 'cache', "post_{$post->ID}" ) );
818938
wp_cache_flush();
819939
}
820940

821941
public function prune_url_transients( $url ) {
822-
global $wpdb;
823942
$url = md5( $url );
824-
$wpdb->get_results( $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s", "_transient_wp_rocket_async_css_style_url_{$url}%", "_transient_timeout_wp_rocket_async_css_style_url_{$url}%" ) );
825-
wp_cache_flush();
943+
$this->delete_cache_branch( array( 'cache', "url_{$url}" ) );
826944
}
827945

828946
/**

0 commit comments

Comments
 (0)