@wfalaa, So.. I decided to re-test the WordFence setup and look at the code again to refresh my original memory from 7 months ago.
? I created a brand-new new multi-site, installed with freshly downloaded WordPress and WordFence, empty DB.
? No themes installed other than what is embedded in WordPress archive.
? ONLY plugin installed, other than WordFence, was “Debug Bar” so I could more easily watch for any DB failures..
Then into WordFence admin. Magically, no failing DB accesses on Blocking or firewall pages. And adding a new blocked IP worked. Showing itself on the Blocking page as expected.
My normal install (where everything is failing) is also a fresh install. With the Network domain on a clean BLOG-ID 1. Now, why is that. There is one MAJOR difference between the two fresh installs. That the normal system of course has all the usual plugins and themes installed as well..
Then back into your code to refresh my memory of the many ways your code tries to access your private tables.
Although, if this was my code, I would do some SERIOUS refactoring to make the code logical, less confusing to maintainers, and more consistent, there a some ways that work despite lack of logic, and at least one method that SHOULD NEVER EXIST.
First Method 1. The access method that MUST be changed if you want your code to work consistently without seemingly random DB failures on various sites..
In wfActivityReport.php and wordfenceHash.php you attempt to access your private tables (always installed off $wpdb->base_prefix) using two variations of “$wpdb->prefix”. As “$wpdb->prefix” directly, and as “$this->db->prefix”, where “$this->db” always represents a link to the system-global “$wpdb”.
In wfNotifications.php directly from the systems global $wpdb as “$wpdb-prefix”.
This direct access of $wpdb->prefix (using two different methods no less) MUST change if you want your code to work consistently.
The global $wpdb and it’s property “prefix” is NOT your structure, NOT your property, and you have no control over its content. No control over whether “prefix” actually at a given time represent the value of “base_prefix” (no blog-number ID suffix) by the time your code runs, which is what you ALWAYS need to find your tables. Under some ideal circumstances with no outside intervention (like my new empty install with no other code), it can equal “base_prefix”, but in most others it cannot be trusted. The purpose of “prefix” is not normally to point to base_prefix. It is the value to current Blog tables.
$wpdb->prefix can be impacted through side-effects from plugins/themes/filter functions/actions/code that may run before you. $wpdb->prefix normal content is != base_prefix on a busy running system. $wpdb’s property “prefix” will usually be set to any of various “dbprefix_#_” pointing to a blog-local prefix.
Here are all the other ways your code uses to “find” your private tables..
For readability and easier maintenance, personally I would restructure/refactor, but in fact none of these methods fail, I believe. (By accident more than long-term forethought one might imagine. ?? )
Method 2: in wordfenceHash.php. Calls on your private tables using code like
“$this->db->prefix()->tablename”
Mind the potential confusion. Notice the “()”s. In the other classes mentioned above “$this->db” always refers to WordPress’ own $wpdb and “prefix” is a variable property.
Here, instead it refers to class wfDB(), your private DB structure, and “prefix” is a function.
But, since prefix() ALWAYS simply returns the value of the global variable “$wpdb->base_prefix”, it actually always works, as “base_prefix” is always what you need.
If I were the maintainer, I would refactor to more maintainable code, but not physically necessary.
Method 3: wordfenceClass.php, wfNotification.php, and wordfenceScanner.php. Using wfDB::networkPrefix() to find a prefix.
networkPrefix tries to find the prefix for your private tables by calling “get_blog_prefix(0)”.
The “0” parameter is important here, because in a multi-site setup, that makes get_blog_prefix() always return “$wpdb->base_prefix”. Since that is what you need, it always works.
Again, refactoring for consistency and to stop all the many access methods might give better code, but this actually always works.
Method 4: used in variation in almost all DB related classes/source files.
As a hard-coded “$this->db->base_prefix”.
This obviously works. As long as your private “$this->db” always point to the global “$wpdb” and not a wfDB() structure, like it does in some locations, it is the equivalent of saying “$wpdb->base_prefix”.
Since your tables were all installed off a hard-coded “$wpdb->base_prefix”, it is the right location.
Method 5: Used in many files. Using global “$wpdb->base_prefix” directly.
Always works, because that is how the tables were installed.
Method 6: abstract function getTable() used to find the wfHits table.
Returns $this->getDB()->base_prefix . ‘wfHits’.
Always works since “getDB()” always returns global $wpdb. So this is the equivalent to “$wpdb->base_prefix” (Method 5) and indirectly to Method 4 as well. Another confusing way to find table prefixes added, but not wrong.
So to recap.. Method 1 (going for any value of “$wpdb->prefix” is INVALID and must be changed if you want WordFence to work in multisite environments in a consistent manner (where other plugins/actions/filters/…) do not affect your workings in seemingly random ways. As “prefix” cannot be trusted to always point to “base_prefix”
Methods 2 – 6 are merely confusing to anyone trying to read or maintain all that code, but all actually work out, because all methods, through a variety of paths, all use “$wpdb->base_prefix”.
Since that is where you installed your tables, that is where they will be found.
If it were my code, I would do some serious refactoring for consistency, but thats not necessary to fix the failures caused by method 1.