diff --git a/WordPress/Tests/NamingConventions/PrefixAllGlobalsUnitTest.1.inc b/WordPress/Tests/NamingConventions/PrefixAllGlobalsUnitTest.1.inc index 011e250b7f..e1142d9b3c 100644 --- a/WordPress/Tests/NamingConventions/PrefixAllGlobalsUnitTest.1.inc +++ b/WordPress/Tests/NamingConventions/PrefixAllGlobalsUnitTest.1.inc @@ -683,4 +683,16 @@ class Acronym_AsymmetricVisibilityProperties { public function __construct(public protected(set) int $foo = 0) {} // Ok. } +/* + * Safeguard correct handling of all types of namespaced function calls. + */ +\define('SOME_GLOBAL', [ 1, 2, 3 ]); // Bad. +MyNamespace\define('SOME_GLOBAL', [ 1, 2, 3 ]); // Ok. +\MyNamespace\define('SOME_GLOBAL', [ 1, 2, 3 ]); // Ok. +namespace\define('SOME_GLOBAL', [ 1, 2, 3 ]); // Ok. The sniff should start flagging this once it can resolve relative namespaces. +\do_action( 'plugin_action' ); // Bad. +MyNamespace\do_action( 'plugin_action' ); // Ok. +\MyNamespace\do_action( 'plugin_action' ); // Ok. +namespace\do_action( 'plugin_action' ); // Ok. The sniff should start flagging this once it can resolve relative namespaces. + // phpcs:set WordPress.NamingConventions.PrefixAllGlobals prefixes[] diff --git a/WordPress/Tests/NamingConventions/PrefixAllGlobalsUnitTest.3.inc b/WordPress/Tests/NamingConventions/PrefixAllGlobalsUnitTest.3.inc index be1eb3627f..a909f6bd83 100644 --- a/WordPress/Tests/NamingConventions/PrefixAllGlobalsUnitTest.3.inc +++ b/WordPress/Tests/NamingConventions/PrefixAllGlobalsUnitTest.3.inc @@ -21,4 +21,35 @@ $acronym_test = new class extends \PHPUnit_Framework_TestCase { } }; +/* + * Safeguard correct handling of namespaced extending classes. + */ +class Some_Test extends PHPUnit_Framework_TestCase { + + public function testPass() { + do_action( 'some-action', $something ); + } +} + +class Some_Test extends MyNamespace\PHPUnit_Framework_TestCase { + + public function testPass() { + do_action( 'some-action', $something ); + } +} + +class Some_Test extends \MyNamespace\PHPUnit_Framework_TestCase { + + public function testPass() { + do_action( 'some-action', $something ); + } +} + +class Some_Test extends namespace\PHPUnit_Framework_TestCase { + + public function testPass() { + do_action( 'some-action', $something ); + } +} + // phpcs:set WordPress.NamingConventions.PrefixAllGlobals prefixes[] diff --git a/WordPress/Tests/NamingConventions/PrefixAllGlobalsUnitTest.php b/WordPress/Tests/NamingConventions/PrefixAllGlobalsUnitTest.php index b9beb09ff6..aafe4da8b2 100644 --- a/WordPress/Tests/NamingConventions/PrefixAllGlobalsUnitTest.php +++ b/WordPress/Tests/NamingConventions/PrefixAllGlobalsUnitTest.php @@ -96,6 +96,8 @@ public function getErrorList( $testFile = 'PrefixAllGlobalsUnitTest.1.inc' ) { 616 => 1, 617 => 1, 633 => 1, + 689 => 1, + 693 => 1, ); case 'PrefixAllGlobalsUnitTest.4.inc': @@ -104,10 +106,17 @@ public function getErrorList( $testFile = 'PrefixAllGlobalsUnitTest.1.inc' ) { 18 => 1, ); + case 'PrefixAllGlobalsUnitTest.3.inc': + // Test class - non-prefixed constant is fine. + return array( + 30 => 1, + 37 => 1, + 44 => 1, + 51 => 1, + ); + case 'PrefixAllGlobalsUnitTest.2.inc': // Namespaced - all OK, fall through to the default case. - case 'PrefixAllGlobalsUnitTest.3.inc': - // Test class - non-prefixed constant is fine, fall through to the default case. default: return array(); } diff --git a/WordPress/Tests/NamingConventions/ValidHookNameUnitTest.1.inc b/WordPress/Tests/NamingConventions/ValidHookNameUnitTest.1.inc index 830c3552d6..c983dbcc8e 100644 --- a/WordPress/Tests/NamingConventions/ValidHookNameUnitTest.1.inc +++ b/WordPress/Tests/NamingConventions/ValidHookNameUnitTest.1.inc @@ -121,3 +121,14 @@ do_action( 'admin_head_' . $fn( 'UPPERCASE', 'wrong-delimiter' ) . '_action' ); do_action_ref_array( hook: 'My-Hook', args: $args ); // OK. Well, not really, but using the wrong parameter name, so not our concern. do_action_ref_array( args: $args, hook_name: 'my_hook', ); // OK. do_action_ref_array( args: $args, hook_name: 'My-Hook', ); // Error - use lowercase + warning about dash. + +/* + * Safeguard correct handling of all types of namespaced function calls. + */ +\apply_filters( 'adminHead', $variable ); // Error. +MyNamespace\apply_filters( 'adminHead', $variable ); // Ok. +\MyNamespace\apply_filters( 'adminHead', $variable ); // Ok. +namespace\apply_filters( 'adminHead', $variable ); // Ok. The sniff should start flagging this once it can resolve relative namespaces. +do_action( 'admin_head_' . MyNamespace\my_function('UPPERCASE') . '_action' ); // Ok. +do_action( 'admin_head_' . \MyNamespace\my_function('UPPERCASE') . '_action' ); // Ok. +do_action( 'admin_head_' . namespace\my_function('UPPERCASE') . '_action' ); // Ok. diff --git a/WordPress/Tests/NamingConventions/ValidHookNameUnitTest.php b/WordPress/Tests/NamingConventions/ValidHookNameUnitTest.php index aac97da195..98649fb620 100644 --- a/WordPress/Tests/NamingConventions/ValidHookNameUnitTest.php +++ b/WordPress/Tests/NamingConventions/ValidHookNameUnitTest.php @@ -75,6 +75,7 @@ public function getErrorList( $testFile = 'ValidHookNameUnitTest.1.inc' ) { 114 => 1, 115 => 1, 123 => 1, + 128 => 1, ); case 'ValidHookNameUnitTest.2.inc': diff --git a/WordPress/Tests/PHP/NoSilencedErrorsUnitTest.inc b/WordPress/Tests/PHP/NoSilencedErrorsUnitTest.inc index f007d150bd..45f7bef881 100644 --- a/WordPress/Tests/PHP/NoSilencedErrorsUnitTest.inc +++ b/WordPress/Tests/PHP/NoSilencedErrorsUnitTest.inc @@ -84,3 +84,11 @@ $decoded = @hex2bin( $data ); // phpcs:set WordPress.PHP.NoSilencedErrors context_length 0 echo @some_userland_function( $param ); // Bad. // phpcs:set WordPress.PHP.NoSilencedErrors context_length 6 + +/* + * Safeguard correct handling of namespaced function calls (fully qualified is already tested above). + */ +$file = @MyNS\MyClass::file_get_contents( $file ); // Bad. +$file = @MyNS\MyClass\file_get_contents( $file ); // Bad. +$file = @namespace\MyNS\MyClass::file_get_contents( $file ); // Bad. +$file = @namespace\file_get_contents( $file ); // The sniff should stop flagging this once it can resolve relative namespaces. diff --git a/WordPress/Tests/PHP/NoSilencedErrorsUnitTest.php b/WordPress/Tests/PHP/NoSilencedErrorsUnitTest.php index 7a576b992c..038c2c8d71 100644 --- a/WordPress/Tests/PHP/NoSilencedErrorsUnitTest.php +++ b/WordPress/Tests/PHP/NoSilencedErrorsUnitTest.php @@ -61,6 +61,10 @@ public function getWarningList() { 71 => 1, 78 => 1, 85 => 1, + 91 => 1, + 92 => 1, + 93 => 1, + 94 => 1, ); } } diff --git a/WordPress/Tests/Security/NonceVerificationUnitTest.1.inc b/WordPress/Tests/Security/NonceVerificationUnitTest.1.inc index aee51ae39a..9e01f33a92 100644 --- a/WordPress/Tests/Security/NonceVerificationUnitTest.1.inc +++ b/WordPress/Tests/Security/NonceVerificationUnitTest.1.inc @@ -524,3 +524,88 @@ function different_function_name() { update_post_meta( (int) $_POST['id'], 'a_key', $_POST['a_value'] ); } // phpcs:set WordPress.Security.NonceVerification customNonceVerificationFunctions[] + +function test_fully_qualified_call_to_global_nonce_verification_function() { + if ( ! is_numeric ( $_POST['foo'] ) ) { + return; + } + + \wp_verify_nonce( 'some_action' ); // OK. +} + +function test_namespaced_calls_to_incorrect_functions() { + if ( ! is_numeric ( $_POST['foo'] ) ) { + return; + } + + MyNamespace\wp_verify_nonce( 'some_action' ); // Bad. + \MyNamespace\wp_verify_nonce( 'some_action' ); // Bad. + namespace\wp_verify_nonce( 'some_action' ); // Bad, but should become ok once the sniff is able to resolve relative namespaces. +} + +function allow_fully_qualified_key_exists_functions() { + if ( \array_key_exists('foo', $_POST) === false ) { // OK. + return; + } + + wp_verify_nonce( 'some_action' ); +} + +function disallow_namespaced_key_exists_functions() { + if ( MyNamespace\array_key_exists( 'foo', $_POST ) === false // Bad. + || \MyNamespace\array_key_exists( 'foo', $_POST ) === false // Bad. + || namespace\array_key_exists( 'foo', $_POST ) === false // Bad, but should become ok once the sniff is able to resolve relative namespaces. + ) { + return; + } + + wp_verify_nonce( 'some_action' ); +} + +function allow_fully_qualified_type_test_functions() { + if ( ! \is_numeric ( $_POST['foo'] ) ) { // OK. + return; + } + + \wp_verify_nonce( 'some_action' ); // OK. +} + +function disallow_namespaced_type_test_functions() { + if ( ! MyNamespace\is_numeric( $_POST['foo'] ) // Bad. + || ! MyNamespace\is_numeric( $_POST['foo'] ) // Bad. + || ! namespace\is_numeric( $_POST['foo'] ) ) // Bad, but should become ok once the sniff is able to resolve relative namespaces. + { + return; + } + + \wp_verify_nonce( 'some_action' ); // OK. +} + +function allow_fully_qualified_array_comparison_functions() { + if ( \in_array( $_GET['action'], $valid_actions, true ) ) { // OK. + check_admin_referer( 'foo' ); + } +} + +function disallow_namespaced_array_comparison_functions() { + if ( MyNamespace\in_array( $_GET['action'], $valid_actions, true ) // Bad. + || \MyNamespace\in_array( $_GET['action'], $valid_actions, true ) // Bad. + || namespace\in_array( $_GET['action'], $valid_actions, true ) // Bad, but should become ok once the sniff is able to resolve relative namespaces. + ) { + check_admin_referer( 'foo' ); + } +} + +function allow_fully_qualified_unslashing_functions() { + $var = \stripslashes_from_strings_only( $_POST['foo'] ); // OK. + wp_verify_nonce( $var ); + echo $var; +} + +function disallow_namespaced_unslashing_functions() { + $var = MyNamespace\stripslashes_from_strings_only( $_POST['foo'] ); // Bad. + $var = \MyNamespace\stripslashes_from_strings_only( $_POST['foo'] ); // Bad. + $var = namespace\stripslashes_from_strings_only( $_POST['foo'] ); // Bad, but should become ok once the sniff is able to resolve relative namespaces. + wp_verify_nonce( $var ); + echo $var; +} diff --git a/WordPress/Tests/Security/NonceVerificationUnitTest.php b/WordPress/Tests/Security/NonceVerificationUnitTest.php index aa5e832e83..1a74732b32 100644 --- a/WordPress/Tests/Security/NonceVerificationUnitTest.php +++ b/WordPress/Tests/Security/NonceVerificationUnitTest.php @@ -75,6 +75,16 @@ public function getErrorList( $testFile = '' ) { 470 => 1, 478 => 1, 524 => 2, + 537 => 1, + 555 => 1, + 556 => 1, + 557 => 1, + 574 => 1, + 575 => 1, + 576 => 1, + 606 => 1, + 607 => 1, + 608 => 1, ); case 'NonceVerificationUnitTest.2.inc': @@ -107,6 +117,9 @@ public function getWarningList( $testFile = '' ) { return array( 365 => 1, 379 => 1, + 591 => 1, + 592 => 1, + 593 => 1, ); case 'NonceVerificationUnitTest.4.inc': diff --git a/WordPress/Tests/Utils/I18nTextDomainFixerUnitTest.4.inc b/WordPress/Tests/Utils/I18nTextDomainFixerUnitTest.4.inc index d33d0a18e0..fb5e1b8526 100644 --- a/WordPress/Tests/Utils/I18nTextDomainFixerUnitTest.4.inc +++ b/WordPress/Tests/Utils/I18nTextDomainFixerUnitTest.4.inc @@ -281,5 +281,13 @@ __ ( $args ); +/* + * Safeguard correct handling of namespaced function calls (partially qualified is already tested above). + */ +\MyNamespace\load_textdomain( 'text-domain', '/path/to/file.mo' ); +namespace\load_textdomain( 'text-domain', '/path/to/file.mo' ); +\load_textdomain( 'text-domain', '/path/to/file.mo' ); +\load_textdomain(); + // phpcs:set WordPress.Utils.I18nTextDomainFixer old_text_domain[] // phpcs:set WordPress.Utils.I18nTextDomainFixer new_text_domain false diff --git a/WordPress/Tests/Utils/I18nTextDomainFixerUnitTest.4.inc.fixed b/WordPress/Tests/Utils/I18nTextDomainFixerUnitTest.4.inc.fixed index f7fd2c6f4e..f47da4e173 100644 --- a/WordPress/Tests/Utils/I18nTextDomainFixerUnitTest.4.inc.fixed +++ b/WordPress/Tests/Utils/I18nTextDomainFixerUnitTest.4.inc.fixed @@ -287,5 +287,13 @@ __ ( 'something-else' ); +/* + * Safeguard correct handling of namespaced function calls (partially qualified is already tested above). + */ +\MyNamespace\load_textdomain( 'text-domain', '/path/to/file.mo' ); +namespace\load_textdomain( 'text-domain', '/path/to/file.mo' ); +\load_textdomain( 'something-else', '/path/to/file.mo' ); +\load_textdomain( 'something-else' ); + // phpcs:set WordPress.Utils.I18nTextDomainFixer old_text_domain[] // phpcs:set WordPress.Utils.I18nTextDomainFixer new_text_domain false diff --git a/WordPress/Tests/Utils/I18nTextDomainFixerUnitTest.php b/WordPress/Tests/Utils/I18nTextDomainFixerUnitTest.php index a8c7c95e84..872050aa97 100644 --- a/WordPress/Tests/Utils/I18nTextDomainFixerUnitTest.php +++ b/WordPress/Tests/Utils/I18nTextDomainFixerUnitTest.php @@ -154,6 +154,8 @@ public function getErrorList( $testFile = '' ) { 245 => 1, 277 => 1, 278 => 1, + 289 => 1, + 290 => 1, ); default: diff --git a/WordPress/Tests/WP/CronIntervalUnitTest.inc b/WordPress/Tests/WP/CronIntervalUnitTest.inc index e9541f49d2..a2623c4956 100644 --- a/WordPress/Tests/WP/CronIntervalUnitTest.inc +++ b/WordPress/Tests/WP/CronIntervalUnitTest.inc @@ -165,7 +165,7 @@ add_filter( 'cron_schedules', function ( $schedules ) { class FQNConstants { public function add_schedules() { add_filter( 'cron_schedules', array( $this, 'add_weekly_schedule' ) ); // Ok: > 15 min. - add_filter( 'cron_schedules', array( $this, 'add_eight_minute_schedule' ) ); // Warning: 8 min. + \add_filter( 'cron_schedules', array( $this, 'add_eight_minute_schedule' ) ); // Warning: 8 min. add_filter( 'cron_schedules', array( $this, 'add_hundred_minute_schedule' ) ); // Warning: time undetermined. add_filter( 'cron_schedules', array( $this, 'sneaky_fake_wp_constant_schedule' ) ); // Warning: time undetermined. } @@ -326,3 +326,12 @@ function first_class_six_min_schedule( $schedules ) { } add_filter( 'cron_schedules', first_class_six_min_schedule(...)); // Warning: 6 min. add_filter( 'cron_schedules', 'first_class_six_min_schedule'(...)); // Warning: 6 min. +add_filter( 'cron_schedules', \first_class_six_min_schedule(...)); // Warning: 6 min. + +/* + * Safeguard correct handling of all types of namespaced function calls (except FQN global function call which is + * handled above). + */ +MyNamespace\add_filter( 'cron_schedules', 'unknown_callback' ); // Ok. +\MyNamespace\add_filter( 'cron_schedules', 'unknown_callback' ); // Ok. +namespace\add_filter( 'cron_schedules', 'unknown_callback' ); // Ok. The sniff should start flagging this once it can resolve relative namespaces. diff --git a/WordPress/Tests/WP/CronIntervalUnitTest.php b/WordPress/Tests/WP/CronIntervalUnitTest.php index 81f02c2768..e70db87175 100644 --- a/WordPress/Tests/WP/CronIntervalUnitTest.php +++ b/WordPress/Tests/WP/CronIntervalUnitTest.php @@ -67,6 +67,7 @@ public function getWarningList() { 290 => 1, 327 => 1, 328 => 1, + 329 => 1, ); } } diff --git a/WordPress/Tests/WP/DiscouragedConstantsUnitTest.inc b/WordPress/Tests/WP/DiscouragedConstantsUnitTest.inc index ea8ae72524..bed0914d53 100644 --- a/WordPress/Tests/WP/DiscouragedConstantsUnitTest.inc +++ b/WordPress/Tests/WP/DiscouragedConstantsUnitTest.inc @@ -102,3 +102,11 @@ enum ContainsConst { } echo HEADER_TEXTCOLOR::$var; // OK. + +/* + * Safeguard correct handling of all types of namespaced function calls. + */ +\define( 'STYLESHEETPATH', 'something' ); // Bad. +\MyNamespace\define( 'STYLESHEETPATH', 'something' ); // Ok. +MyNamespace\define( 'STYLESHEETPATH', 'something' ); // Ok. +namespace\define( 'STYLESHEETPATH', 'something' ); // Ok. diff --git a/WordPress/Tests/WP/DiscouragedConstantsUnitTest.php b/WordPress/Tests/WP/DiscouragedConstantsUnitTest.php index e27fd838c2..138d0eb4ef 100644 --- a/WordPress/Tests/WP/DiscouragedConstantsUnitTest.php +++ b/WordPress/Tests/WP/DiscouragedConstantsUnitTest.php @@ -36,26 +36,27 @@ public function getErrorList() { */ public function getWarningList() { return array( - 50 => 1, - 51 => 1, - 52 => 1, - 53 => 1, - 54 => 1, - 55 => 1, - 56 => 1, - 57 => 1, - 58 => 1, - 59 => 1, - 60 => 1, - 61 => 1, - 63 => 1, - 64 => 1, - 66 => 1, - 67 => 1, - 71 => 1, - 72 => 1, - 83 => 1, - 88 => 1, + 50 => 1, + 51 => 1, + 52 => 1, + 53 => 1, + 54 => 1, + 55 => 1, + 56 => 1, + 57 => 1, + 58 => 1, + 59 => 1, + 60 => 1, + 61 => 1, + 63 => 1, + 64 => 1, + 66 => 1, + 67 => 1, + 71 => 1, + 72 => 1, + 83 => 1, + 88 => 1, + 109 => 1, ); } }