diff --git a/WordPress/Helpers/PrintingFunctionsTrait.php b/WordPress/Helpers/PrintingFunctionsTrait.php new file mode 100644 index 0000000000..7fc87f74fd --- /dev/null +++ b/WordPress/Helpers/PrintingFunctionsTrait.php @@ -0,0 +1,112 @@ + true, + '_deprecated_constructor' => true, + '_deprecated_file' => true, + '_deprecated_function' => true, + '_deprecated_hook' => true, + '_doing_it_wrong' => true, + '_e' => true, + '_ex' => true, + 'printf' => true, + 'trigger_error' => true, + 'user_error' => true, + 'vprintf' => true, + 'wp_die' => true, + 'wp_dropdown_pages' => true, + ); + + /** + * Cache of previously added custom functions. + * + * Prevents having to do the same merges over and over again. + * + * @since 0.4.0 + * @since 0.11.0 - Changed from public static to protected non-static. + * - Changed the format from simple bool to array. + * @since 3.0.0 - Moved from the EscapeOutput Sniff class to this class. + * - Visibility changed from protected to private. + * + * @var array + */ + private $addedCustomPrintingFunctions = array(); + + /** + * Combined list of WP/PHP native and custom printing functions. + * + * @since 3.0.0 + * + * @var array + */ + private $allPrintingFunctions = array(); + + /** + * Check if a particular function is regarded as a printing function. + * + * @since 3.0.0 + * + * @param string $functionName The name of the function to check. + * + * @return bool + */ + public function is_printing_function( $functionName ) { + if ( array() === $this->allPrintingFunctions + || $this->customPrintingFunctions !== $this->addedCustomPrintingFunctions + ) { + $this->allPrintingFunctions = RulesetPropertyHelper::merge_custom_array( + $this->customPrintingFunctions, + $this->printingFunctions + ); + + $this->addedCustomPrintingFunctions = $this->customPrintingFunctions; + } + + return isset( $this->allPrintingFunctions[ $functionName ] ); + } +} diff --git a/WordPress/Sniff.php b/WordPress/Sniff.php index 0c15429f08..37ae569d63 100644 --- a/WordPress/Sniff.php +++ b/WordPress/Sniff.php @@ -176,31 +176,6 @@ abstract class Sniff implements PHPCS_Sniff { 'wp_sprintf' => true, ); - /** - * Functions which print output incorporating the values passed to them. - * - * @since 0.5.0 - * @since 0.11.0 Changed from public static to protected non-static. - * - * @var array - */ - protected $printingFunctions = array( - '_deprecated_argument' => true, - '_deprecated_constructor' => true, - '_deprecated_file' => true, - '_deprecated_function' => true, - '_deprecated_hook' => true, - '_doing_it_wrong' => true, - '_e' => true, - '_ex' => true, - 'printf' => true, - 'trigger_error' => true, - 'user_error' => true, - 'vprintf' => true, - 'wp_die' => true, - 'wp_dropdown_pages' => true, - ); - /** * A list of superglobals that incorporate user input. * diff --git a/WordPress/Sniffs/Security/EscapeOutputSniff.php b/WordPress/Sniffs/Security/EscapeOutputSniff.php index 0a12db7953..8ffa8801bb 100644 --- a/WordPress/Sniffs/Security/EscapeOutputSniff.php +++ b/WordPress/Sniffs/Security/EscapeOutputSniff.php @@ -13,9 +13,9 @@ use PHPCSUtils\Utils\PassedParameters; use PHPCSUtils\Utils\TextStrings; use WordPressCS\WordPress\Helpers\ContextHelper; -use WordPressCS\WordPress\Helpers\RulesetPropertyHelper; use WordPressCS\WordPress\Helpers\ConstantsHelper; use WordPressCS\WordPress\Helpers\EscapingFunctionsTrait; +use WordPressCS\WordPress\Helpers\PrintingFunctionsTrait; use WordPressCS\WordPress\Helpers\VariableHelper; use WordPressCS\WordPress\Sniff; @@ -38,15 +38,7 @@ class EscapeOutputSniff extends Sniff { use EscapingFunctionsTrait; - - /** - * Custom list of functions which print output incorporating the passed values. - * - * @since 0.4.0 - * - * @var string|string[] - */ - public $customPrintingFunctions = array(); + use PrintingFunctionsTrait; /** * Printing functions that incorporate unsafe values. @@ -61,22 +53,6 @@ class EscapeOutputSniff extends Sniff { '_ex' => 'echo esc_html_x() or echo esc_attr_x()', ); - /** - * Cache of previously added custom functions. - * - * Prevents having to do the same merges over and over again. - * - * @since 0.4.0 - * @since 0.11.0 - Changed from public static to protected non-static. - * - Changed the format from simple bool to array. - * - * @var array - */ - protected $addedCustomFunctions = array( - 'sanitize' => array(), - 'print' => array(), - ); - /** * List of names of the tokens representing PHP magic constants. * @@ -163,8 +139,6 @@ public function register() { */ public function process_token( $stackPtr ) { - $this->mergeFunctionLists(); - $function = $this->tokens[ $stackPtr ]['content']; // Find the opening parenthesis (if present; T_ECHO might not have it). @@ -173,7 +147,7 @@ public function process_token( $stackPtr ) { // If function, not T_ECHO nor T_PRINT. if ( \T_STRING === $this->tokens[ $stackPtr ]['code'] ) { // Skip if it is a function but is not one of the printing functions. - if ( ! isset( $this->printingFunctions[ $this->tokens[ $stackPtr ]['content'] ] ) ) { + if ( ! $this->is_printing_function( $this->tokens[ $stackPtr ]['content'] ) ) { return; } @@ -454,24 +428,4 @@ public function process_token( $stackPtr ) { return $end_of_statement; } - - /** - * Merge custom functions provided via a custom ruleset with the defaults, if we haven't already. - * - * @since 0.11.0 Split out from the `process()` method. - * - * @return void - */ - protected function mergeFunctionLists() { - if ( $this->customPrintingFunctions !== $this->addedCustomFunctions['print'] ) { - - $this->printingFunctions = RulesetPropertyHelper::merge_custom_array( - $this->customPrintingFunctions, - $this->printingFunctions - ); - - $this->addedCustomFunctions['print'] = $this->customPrintingFunctions; - } - } - } diff --git a/WordPress/Tests/Security/EscapeOutputUnitTest.php b/WordPress/Tests/Security/EscapeOutputUnitTest.php index 3b0fdd842d..187d0e7b92 100644 --- a/WordPress/Tests/Security/EscapeOutputUnitTest.php +++ b/WordPress/Tests/Security/EscapeOutputUnitTest.php @@ -22,6 +22,7 @@ * * @covers \WordPressCS\WordPress\Helpers\ConstantsHelper::is_use_of_global_constant * @covers \WordPressCS\WordPress\Helpers\EscapingFunctionsTrait + * @covers \WordPressCS\WordPress\Helpers\PrintingFunctionsTrait * @covers \WordPressCS\WordPress\Sniffs\Security\EscapeOutputSniff */ final class EscapeOutputUnitTest extends AbstractSniffUnitTest {