: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
private static $cacheStats = array();
private static $cacheClearedThisRequest = false;
private static $lastRecursiveDeleteError = false;
public static function removeCaching() {
$cacheType = wfConfig::get('cacheType', false);
if ($cacheType === 'disabled') {
if ($cacheType == 'falcon') {
self::addHtaccessCode('remove');
self::updateBlockedIPs('remove');
wfConfig::set('cacheType', 'disabled');
$cacheDir = WP_CONTENT_DIR . '/wfcache/';
if (file_exists($cacheDir . '.htaccess')) {
unlink($cacheDir . '.htaccess');
self::clearPageCacheSafe();
public static function clearPageCacheSafe(){
if(self::$cacheClearedThisRequest){ return; }
self::$cacheClearedThisRequest = true;
public static function clearPageCache(){ //If a clear is in progress this does nothing.
self::$cacheStats = array(
$cacheDir = WP_CONTENT_DIR . '/wfcache/';
if (!file_exists($cacheDir)) {
return self::$cacheStats;
$cacheClearLock = WP_CONTENT_DIR . '/wfcache/clear.lock';
if(! is_file($cacheClearLock)){
if(! touch($cacheClearLock)){
self::$cacheStats['error'] = "Could not create a lock file $cacheClearLock to clear the cache.";
self::$cacheStats['totalErrors']++;
return self::$cacheStats;
$fp = fopen($cacheClearLock, 'w');
self::$cacheStats['error'] = "Could not open the lock file $cacheClearLock to clear the cache. Please make sure the directory is writable by your web server.";
self::$cacheStats['totalErrors']++;
return self::$cacheStats;
if(flock($fp, LOCK_EX | LOCK_NB)){ //non blocking exclusive flock attempt. If we get a lock then it continues and returns true. If we don't lock, then return false, don't block and don't clear the cache.
// This logic means that if a cache clear is currently in progress we don't try to clear the cache.
// This prevents web server children from being queued up waiting to be able to also clear the cache.
self::$lastRecursiveDeleteError = false;
self::recursiveDelete(WP_CONTENT_DIR . '/wfcache/');
if(self::$lastRecursiveDeleteError){
self::$cacheStats['error'] = self::$lastRecursiveDeleteError;
self::$cacheStats['totalErrors']++;
@unlink($cacheClearLock);
return self::$cacheStats;
private static function recursiveDelete($dir) {
$files = array_diff(scandir($dir), array('.','..'));
foreach ($files as $file) {
if(is_dir($dir . '/' . $file)){
if(! self::recursiveDelete($dir . '/' . $file)){
if($file == 'clear.lock'){ continue; } //Don't delete our lock file
$size = filesize($dir . '/' . $file);
self::$cacheStats['totalData'] += round($size / 1024);
if(strpos($dir, 'wfcache/') === false){
self::$lastRecursiveDeleteError = "Not deleting file in directory $dir because it appears to be in the wrong path.";
self::$cacheStats['totalErrors']++;
return false; //Safety check that we're in a subdir of the cache
if(@unlink($dir . '/' . $file)){
self::$cacheStats['filesDeleted']++;
self::$lastRecursiveDeleteError = "Could not delete file " . $dir . "/" . $file . " : " . wfUtils::getLastError();
self::$cacheStats['totalErrors']++;
if($dir != WP_CONTENT_DIR . '/wfcache/'){
if(strpos($dir, 'wfcache/') === false){
self::$lastRecursiveDeleteError = "Not deleting directory $dir because it appears to be in the wrong path.";
self::$cacheStats['totalErrors']++;
return false; //Safety check that we're in a subdir of the cache
self::$cacheStats['dirsDeleted']++;
self::$lastRecursiveDeleteError = "Could not delete directory $dir : " . wfUtils::getLastError();
self::$cacheStats['totalErrors']++;
public static function addHtaccessCode($action){
die("Error: addHtaccessCode must be called with 'remove' as param");
$htaccessPath = self::getHtaccessPath();
return "Wordfence could not find your .htaccess file.";
$fh = @fopen($htaccessPath, 'r+');
fseek($fh, 0, SEEK_SET); //start of file
$contents = fread($fh, filesize($htaccessPath));
return "Could not read from $htaccessPath";
$contents = preg_replace('/#WFCACHECODE.*WFCACHECODE[\r\s\n\t]*/s', '', $contents);
* @return bool|string|void
public static function updateBlockedIPs($action){ //'add' or 'remove'
$htaccessPath = self::getHtaccessPath();
return "Wordfence could not find your .htaccess file.";
$fh = @fopen($htaccessPath, 'r+');
fseek($fh, 0, SEEK_SET); //start of file
$contents = @fread($fh, filesize($htaccessPath));
return "Could not read from $htaccessPath";
$contents = preg_replace('/#WFIPBLOCKS.*WFIPBLOCKS[\r\s\n\t]*/s', '', $contents);
public static function getHtaccessPath(){
$homePath = wfUtils::getHomePath();
$htaccessFile = $homePath.'.htaccess';
public static function doNotCache(){
if(! defined('WFDONOTCACHE')){
define('WFDONOTCACHE', true);