Created
December 16, 2021 13:26
-
-
Save mklepaczewski/51817ee3d43f792a475f68fee154d723 to your computer and use it in GitHub Desktop.
Patch for wpDiscuz bug where persistent cache is being used and 'Load more comments' button loads the same comments
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
Plugin Name: FasterWebsite wpDiscuz Cache Patch | |
Plugin URI: https://fasterwebsite.com/ | |
Description: Fixes bug 'Load More button loads the same comments' | |
Author: Maciej Klepaczewski | |
Author URI: https://fasterwebsite.com/ | |
Version: 0.1 | |
Requires PHP: 7.4 | |
*/ | |
/** | |
* @author Maciej Klepaczewski <[email protected]> | |
* @link https://fasterwebsite.com/ | |
* @copyright Copyright (c) 2021, Maciej Klepaczewski FasterWebsite.com | |
*/ | |
declare(strict_types=1); | |
namespace fasterwebsite\wpdiscuz\patch1; | |
use WP_Comment_Query; | |
/** | |
* | |
* Patch for bug where when persistent caching is enabled wpDiscuz will fail to load next batch of comments when | |
* 'Load More Comments' button is clicked. | |
* | |
* Why it happens: | |
* The problem is in caching done by WP_Comment_Query::get_comments(). The method generates cache key based only on | |
* WP_Comment_Query::query_var_defaults, which does not hold some keys that are being injected into SQL query to fetch | |
* comments by wpDiscuz WpdiscuzCore::commentsClauses() (which hooks into 'comments_clauses' hook fired by | |
* WP_Comment_Query::get_comment_ids()). The result is that two requests with different "lastParentId" parameters have the | |
* same cache key. When persistent cache is enabled (Redis, Memcached etc.) this results in retrieving incorrect comments | |
* for the request. | |
* | |
* Solution: | |
* WP_Comment_Query::get_comments() uses WP_Comment_Query::query_vars to generate the cache key | |
* WP_Comment_Query::get_comments() considers only those parameters in WP_Comment_Query::query_vars that are defined | |
* in WP_Comment_Query::default_query_vars. So, the solution is: | |
* - hook into 'comments_pre_query' and inject into WP_Comment_Query::default_query_vars our custom variables so they | |
* are being taken into account while generating cache key. Also, inject actual values into WP_Comment_Query::query_vars | |
* - let WP_Comment_Query generate the cache key | |
* - remove our changes after cache key has been generated, as soon as possible. This happens by hooking into the | |
* 'the_comments' hook and removing our changes from both WP_Comment_Query::default_query_vars and WP_Comment_Query::query_vars | |
* | |
* Note that wpDiscuz injects some variables into WP_Comment_Query::query_vars and we could add these using | |
* WP_Comment_Query::default_query_vars, but it seems to be more intrusive and requires more knowledge. | |
*/ | |
class Patch { | |
public function __construct() { | |
if(!$this->isApplicableToRequest()) { | |
return; | |
} | |
/* This will inject our custom variable into WP_Comment_Query::query_var_defaults and query_vars */ | |
add_filter('comments_pre_query', function($comment_data, WP_Comment_Query $query) { | |
$query->query_var_defaults['wpdiscuz'] = 'temporary_from_' . __CLASS__ . "::" . __METHOD__; | |
$this->addWpDiscuzParams($query); | |
/* Don't change $comment_data */ | |
return $comment_data; | |
}, PHP_INT_MAX, 2); | |
/* This will remove it */ | |
add_filter('the_comments', function($_comments, WP_Comment_Query $query) { | |
unset($query->query_var_defaults['wpdiscuz']); | |
return $_comments; | |
}, PHP_INT_MIN, 2); | |
} | |
/** | |
* Decides if this patch should actually run. | |
* | |
* We run it | |
* @return bool | |
*/ | |
public function isApplicableToRequest() : bool { | |
if(!wp_doing_ajax()) { | |
return false; | |
} | |
if(!isset($_REQUEST['action']) || $_REQUEST['action'] !== 'wpdLoadMoreComments') { | |
return false; | |
} | |
return true; | |
} | |
private function addWpDiscuzParams(WP_Comment_Query $query) : void { | |
$query->query_vars['wpdiscuz'] = wp_array_slice_assoc($_REQUEST, $this->getWpDiscuzSpecificArgs()); | |
} | |
/** | |
* @return array<string> | |
*/ | |
private function getWpDiscuzSpecificArgs() : array { | |
return ['lastParentId', 'isFirstLoad', "offset", "sorting"]; | |
} | |
} | |
new Patch(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment