diff --git a/lib/classes/class-utility.php b/lib/classes/class-utility.php index 95aca38bd..294f48a99 100644 --- a/lib/classes/class-utility.php +++ b/lib/classes/class-utility.php @@ -602,8 +602,55 @@ function_exists('is_wp_version_compatible') && return false; } - } + /** + * Useful when there is a need to do things depending on a call stack. + * Returns true if any of the conditions met. Returns false otherwise. + * + * @param $callstack array Result of debug_backtrace function. + * @param $conditions array CallStack fingerprint with `stack_level` integer. + * + * Example: + * array( + * array( + * 'stack_level' => 4, + * 'function' => '__construct', + * 'class' => 'ET_Core_PageResource' + * ), + * array( + * 'stack_level' => 4, + * 'function' => 'get_cache_filename', + * 'class' => 'ET_Builder_Element' + * ) + * ) + * + * @return bool + */ + public static function isCallStackMatches( $callstack, $conditions ) { + if ( !is_array( $conditions ) ) { + $conditions = array( $conditions ); + } - } + foreach( $conditions as $condition ) { + $condition['stack_level'] = $condition['stack_level'] ? $condition['stack_level'] : 0; + + $levelData = $callstack[$condition['stack_level']]; + + unset( $condition['stack_level'] ); -} + $levelMatches = false; + foreach( $condition as $key => $value ) { + if ( $levelData[ $key ] === $value ) { + $levelMatches = true; + } else { + $levelMatches = false; + } + } + + if ( $levelMatches ) return true; + } + + return false; + } + } + } +} \ No newline at end of file diff --git a/lib/classes/compatibility/divi.php b/lib/classes/compatibility/divi.php index 3851e9832..c2832b748 100644 --- a/lib/classes/compatibility/divi.php +++ b/lib/classes/compatibility/divi.php @@ -16,9 +16,32 @@ class Divi extends ICompatibility { protected $id = 'divi'; protected $title = 'Divi'; protected $constant = 'WP_STATELESS_COMPATIBILITY_DIVI'; - protected $description = 'Ensures compatibility with Divi Builder Export.'; + protected $description = 'Ensures compatibility with Divi theme.'; protected $theme_name = 'Divi'; + /** + * Cache Busting call stack conditions to disable. + * Fixing the issue with multiple cache files being created on each page load. + * @see https://github.com/wpCloud/wp-stateless/issues/430 + * @var array + */ + private $cache_busting_disable_conditions = array( + array( + 'stack_level' => 4, + 'function' => '__construct', + 'class' => 'ET_Core_PageResource' + ), + array( + 'stack_level' => 4, + 'function' => 'get_cache_filename', + 'class' => 'ET_Builder_Element' + ) + ); + + /** + * Initialize compatibility module + * @param $sm + */ public function module_init($sm){ // exclude randomize_filename from export if( @@ -29,7 +52,25 @@ public function module_init($sm){ ) { remove_filter( 'sanitize_file_name', array( "wpCloud\StatelessMedia\Utility", 'randomize_filename' ), 10 ); } - + + // maybe disable the filter + add_filter('sanitize_file_name', array( $this, 'sanitize_file_name' ), 1); + } + + /** + * Check if `sanitize_file_name` filter was called in a place where we don't need our custom filter. + * Remove our 10-priority filter if condition met. + * @param $filename + * @return mixed + */ + public function sanitize_file_name( $filename ) { + $callstack = debug_backtrace( DEBUG_BACKTRACE_PROVIDE_OBJECT, 5 ); + + if ( Utility::isCallStackMatches( $callstack, $this->cache_busting_disable_conditions ) ) { + remove_filter( 'sanitize_file_name', array( "wpCloud\StatelessMedia\Utility", 'randomize_filename' ), 10 ); + } + + return $filename; } }