diff --git a/WordPress/Helpers/WPDBTrait.php b/WordPress/Helpers/WPDBTrait.php index d2f729da5b..5843ea4225 100644 --- a/WordPress/Helpers/WPDBTrait.php +++ b/WordPress/Helpers/WPDBTrait.php @@ -13,6 +13,7 @@ use PHP_CodeSniffer\Util\Tokens; use PHPCSUtils\BackCompat\BCFile; use PHPCSUtils\Tokens\Collections; +use WordPressCS\WordPress\Helpers\ContextHelper; /** * Helper utilities for sniffs which examine WPDB method calls. @@ -79,6 +80,11 @@ final protected function is_wpdb_method_call( File $phpcsFile, $stackPtr, array return false; } + // If calling the method statically, ensure we are calling the global wpdb class. + if ( \T_STRING === $tokens[ $stackPtr ]['code'] && ContextHelper::is_token_namespaced( $phpcsFile, $stackPtr ) ) { + return false; + } + $methodPtr = $phpcsFile->findNext( Tokens::$emptyTokens, ( $is_object_call + 1 ), null, true, null, true ); if ( false === $methodPtr ) { return false; diff --git a/WordPress/Tests/DB/PreparedSQLPlaceholdersUnitTest.inc b/WordPress/Tests/DB/PreparedSQLPlaceholdersUnitTest.inc index 601877bfa4..791df5a509 100644 --- a/WordPress/Tests/DB/PreparedSQLPlaceholdersUnitTest.inc +++ b/WordPress/Tests/DB/PreparedSQLPlaceholdersUnitTest.inc @@ -518,3 +518,17 @@ $where = $wpdb->prepare( */ $callback = $wpdb->prepare(...); // OK. +/* + * Safeguard correct handling of all types of namespaced calls to the wpdb::prepare() method. + * + * Note that calling wpdb::prepare() statically will result in an error. Still, the tests are included here since the + * sniff handles those calls. + * + * Related to: https://github.com/WordPress/WordPress-Coding-Standards/issues/2710. + */ +$sql = \wpdb::prepare( "SELECT * FROM $wpdb->users WHERE id = %d AND user_login = %s" ); // Error. +$sql = \WPDB::prepare( "SELECT * FROM $wpdb->users WHERE id = %d AND user_login = %s" ); // Error. +$sql = MyNamespace\wpdb::prepare( "SELECT * FROM $wpdb->users WHERE id = %d AND user_login = %s" ); // OK. +$sql = \MyNamespace\WPDB::prepare( "SELECT * FROM $wpdb->users WHERE id = %d AND user_login = %s" ); // OK. +$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 as this test file is not namespaced. +$sql = namespace\Sub\wpdb::prepare( "SELECT * FROM $wpdb->users WHERE id = %d AND user_login = %s" ); // OK. diff --git a/WordPress/Tests/DB/PreparedSQLPlaceholdersUnitTest.php b/WordPress/Tests/DB/PreparedSQLPlaceholdersUnitTest.php index df0bc753bf..916567cf3e 100644 --- a/WordPress/Tests/DB/PreparedSQLPlaceholdersUnitTest.php +++ b/WordPress/Tests/DB/PreparedSQLPlaceholdersUnitTest.php @@ -106,6 +106,10 @@ public function getErrorList() { // Named parameter support. 418 => 1, + + // Fully qualified calls to the global class wpdb. + 529 => 1, + 530 => 1, ); } diff --git a/WordPress/Tests/DB/PreparedSQLUnitTest.1.inc b/WordPress/Tests/DB/PreparedSQLUnitTest.1.inc index 1f1a49076c..ac97d71ce8 100644 --- a/WordPress/Tests/DB/PreparedSQLUnitTest.1.inc +++ b/WordPress/Tests/DB/PreparedSQLUnitTest.1.inc @@ -143,5 +143,17 @@ echo $wpdb::CONSTANT_NAME; // Not an identifiable method call. $wpdb->{$methodName}('query'); -// Don't throw an error during live coding. -wpdb::prepare( "SELECT * FROM $wpdb->posts +/* + * Safeguard correct handling of all types of namespaced calls to the wpdb::prepare() method. + * + * Note that calling wpdb::prepare() statically will result in an error. Still, the tests are included here since the + * sniff handles those calls. + * + * Related to: https://github.com/WordPress/WordPress-Coding-Standards/issues/2710. + */ +\wpdb::prepare( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '" . foo() . "';" ); // Bad. +\WPDB::prepare( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '" . foo() . "';" ); // Bad. +MyNamespace\wpdb::prepare( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '" . foo() . "';" ); // Ok. +\MyNamespace\WPDB::prepare( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '" . foo() . "';" ); // Ok. +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 as this test file is not namespaced. +namespace\Sub\wpdb::prepare( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '" . foo() . "';" ); // Ok. diff --git a/WordPress/Tests/DB/PreparedSQLUnitTest.3.inc b/WordPress/Tests/DB/PreparedSQLUnitTest.3.inc new file mode 100644 index 0000000000..4047216b82 --- /dev/null +++ b/WordPress/Tests/DB/PreparedSQLUnitTest.3.inc @@ -0,0 +1,8 @@ +posts diff --git a/WordPress/Tests/DB/PreparedSQLUnitTest.php b/WordPress/Tests/DB/PreparedSQLUnitTest.php index 0a296ff984..8d887dd044 100644 --- a/WordPress/Tests/DB/PreparedSQLUnitTest.php +++ b/WordPress/Tests/DB/PreparedSQLUnitTest.php @@ -66,6 +66,8 @@ public function getErrorList( $testFile = '' ) { 124 => 1, 128 => 1, 132 => 2, + 154 => 1, + 155 => 1, ); case 'PreparedSQLUnitTest.2.inc':