Skip to content

Commit c3d9248

Browse files
committed
WPDBTrait::is_wpdb_method_call(): fix false positives for static method calls to non-global classes called wpdb
The `DB/PreparedSQL` and `DB/PreparedSQLPlaceholders` sniffs were producing false positives for static method calls to a class named `wpdb` that is preceded by a namespace. The root cause was in `WPDBTrait::is_wpdb_method_call()`, which did not check whether the `wpdb` token was namespaced before treating it as a call to the global `wpdb` class. The fix makes the method return `false` when the `wpdb` token is a namespaced call to a non-global `wpdb` class. Fixes 2710
1 parent 4ec02fc commit c3d9248

5 files changed

Lines changed: 41 additions & 0 deletions

File tree

WordPress/Helpers/WPDBTrait.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use PHP_CodeSniffer\Util\Tokens;
1414
use PHPCSUtils\BackCompat\BCFile;
1515
use PHPCSUtils\Tokens\Collections;
16+
use WordPressCS\WordPress\Helpers\ContextHelper;
1617

1718
/**
1819
* Helper utilities for sniffs which examine WPDB method calls.
@@ -79,6 +80,11 @@ final protected function is_wpdb_method_call( File $phpcsFile, $stackPtr, array
7980
return false;
8081
}
8182

83+
// If calling the method statically, ensure we are calling the global wpdb class.
84+
if ( \T_STRING === $tokens[ $stackPtr ]['code'] && ContextHelper::is_token_namespaced( $phpcsFile, $stackPtr ) ) {
85+
return false;
86+
}
87+
8288
$methodPtr = $phpcsFile->findNext( Tokens::$emptyTokens, ( $is_object_call + 1 ), null, true, null, true );
8389
if ( false === $methodPtr ) {
8490
return false;

WordPress/Tests/DB/PreparedSQLPlaceholdersUnitTest.inc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,3 +518,17 @@ $where = $wpdb->prepare(
518518
*/
519519
$callback = $wpdb->prepare(...); // OK.
520520

521+
/*
522+
* Safeguard correct handling of all types of namespaced calls to the wpdb::prepare() method.
523+
*
524+
* Note that calling wpdb::prepare() statically will result in an error. Still, the tests are included here since the
525+
* sniff handles those calls.
526+
*
527+
* Related to: https://github.com/WordPress/WordPress-Coding-Standards/issues/2710.
528+
*/
529+
$sql = \wpdb::prepare( "SELECT * FROM $wpdb->users WHERE id = %d AND user_login = %s" ); // Error.
530+
$sql = \WPDB::prepare( "SELECT * FROM $wpdb->users WHERE id = %d AND user_login = %s" ); // Error.
531+
$sql = MyNamespace\wpdb::prepare( "SELECT * FROM $wpdb->users WHERE id = %d AND user_login = %s" ); // OK.
532+
$sql = \MyNamespace\WPDB::prepare( "SELECT * FROM $wpdb->users WHERE id = %d AND user_login = %s" ); // OK.
533+
$sql = namespace\wpdb::prepare( "SELECT * FROM $wpdb->users WHERE id = %d AND user_login = %s" ); // Ok. The sniff should start flagging this once it can resolve relative namespaces.
534+
$sql = namespace\Sub\wpdb::prepare( "SELECT * FROM $wpdb->users WHERE id = %d AND user_login = %s" ); // OK.

WordPress/Tests/DB/PreparedSQLPlaceholdersUnitTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ public function getErrorList() {
106106

107107
// Named parameter support.
108108
418 => 1,
109+
110+
// Fully qualified calls to the global class wpdb.
111+
529 => 1,
112+
530 => 1,
109113
);
110114
}
111115

WordPress/Tests/DB/PreparedSQLUnitTest.1.inc

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,3 +142,18 @@ echo $wpdb::CONSTANT_NAME;
142142

143143
// Not an identifiable method call.
144144
$wpdb->{$methodName}('query');
145+
146+
/*
147+
* Safeguard correct handling of all types of namespaced calls to the wpdb::prepare() method.
148+
*
149+
* Note that calling wpdb::prepare() statically will result in an error. Still, the tests are included here since the
150+
* sniff handles those calls.
151+
*
152+
* Related to: https://github.com/WordPress/WordPress-Coding-Standards/issues/2710.
153+
*/
154+
\wpdb::prepare( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '" . foo() . "';" ); // Bad.
155+
\WPDB::prepare( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '" . foo() . "';" ); // Bad.
156+
MyNamespace\wpdb::prepare( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '" . foo() . "';" ); // Ok.
157+
\MyNamespace\WPDB::prepare( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '" . foo() . "';" ); // Ok.
158+
namespace\wpdb::prepare( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '" . foo() . "';" ); // Ok. The sniff should start flagging this once it can resolve relative namespaces.
159+
namespace\Sub\wpdb::prepare( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '" . foo() . "';" ); // Ok.

WordPress/Tests/DB/PreparedSQLUnitTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ public function getErrorList( $testFile = '' ) {
6666
124 => 1,
6767
128 => 1,
6868
132 => 2,
69+
154 => 1,
70+
155 => 1,
6971
);
7072

7173
case 'PreparedSQLUnitTest.2.inc':

0 commit comments

Comments
 (0)