diff --git a/.travis.yml b/.travis.yml index c6d71fbf72..1a6ffda487 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,19 +9,26 @@ php: - 5.4 - 5.5 - 5.6 + - 7.0 env: - PHPCS_BRANCH=master - - PHPCS_BRANCH=2.2.0 + - PHPCS_BRANCH=2.6.0 matrix: fast_finish: true include: + # Run PHPCS against WPCS. I just picked to run it against 5.5. + - php: 5.5 + env: PHPCS_BRANCH=master SNIFF=1 # Run against PHPCS 3.0. I just picked to run it against 5.6. - php: 5.6 env: PHPCS_BRANCH=3.0 # Run against HHVM and PHP nightly. - php: hhvm + sudo: required + dist: trusty + group: edge env: PHPCS_BRANCH=master - php: nightly env: PHPCS_BRANCH=master @@ -32,6 +39,7 @@ matrix: - env: PHPCS_BRANCH=3.0 before_script: + - if [[ $TRAVIS_PHP_VERSION != "7.0" && $TRAVIS_PHP_VERSION != "nightly" && $TRAVIS_PHP_VERSION != "hhvm" ]]; then phpenv config-add myconfig.ini; fi - export PHPCS_DIR=/tmp/phpcs - export PHPCS_BIN=$(if [[ $PHPCS_BRANCH == 3.0 ]]; then echo $PHPCS_DIR/bin/phpcs; else echo $PHPCS_DIR/scripts/phpcs; fi) - mkdir -p $PHPCS_DIR && git clone --depth 1 https://github.com/squizlabs/PHP_CodeSniffer.git -b $PHPCS_BRANCH $PHPCS_DIR @@ -40,3 +48,13 @@ before_script: script: - if find . -name "*.php" -exec php -l {} \; | grep "^[Parse error|Fatal error]"; then exit 1; fi; - phpunit --filter WordPress /tmp/phpcs/tests/AllTests.php + # WordPress Coding Standards. + # @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + # @link http://pear.php.net/package/PHP_CodeSniffer/ + # -p flag: Show progress of the run. + # -s flag: Show sniff codes in all reports. + # -v flag: Print verbose output. + # -n flag: Do not print warnings. (shortcut for --warning-severity=0) + # --standard: Use WordPress as the standard. + # --extensions: Only sniff PHP files. + - if [[ "$SNIFF" == "1" ]]; then $PHPCS_DIR/scripts/phpcs -p -s -v -n . --standard=./bin/phpcs.xml --extensions=php; fi \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 75116e9519..481cd4bff7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,8 +6,61 @@ This projects adheres to [Semantic Versioning](http://semver.org/) and [Keep a C ## [Unreleased] +_Nothing yet._ + +## [0.10.0] - 2016-08-29 + ### Added -- Sniff to flag dynamic translatable strings and textdomains. +- `WordPress.WP.I18n` sniff to the `WordPress-Core` ruleset to flag dynamic translatable strings and textdomains. +- `WordPress.PHP.DisallowAlternativePHPTags` sniff to the `WordPress-Core` ruleset to flag - and fix - ASP and `' ); + $error_id = 'ScriptOpenTagFound'; + } + + if ( isset( $error, $closer, $error_id ) ) { + $data = array( $content ); + + if ( false === $closer ) { + $phpcsFile->addError( $error, $stackPtr, $error_id, $data ); + } else { + $fix = $phpcsFile->addFixableError( $error, $stackPtr, $error_id, $data ); + if ( true === $fix ) { + $this->add_changeset( $phpcsFile, $tokens, $stackPtr, $closer ); + } + } + } + + return; + } + + if ( T_OPEN_TAG_WITH_ECHO === $openTag['code'] && '<%=' === $content ) { + $error = 'ASP style opening tag used with echo; expected "findNext( T_WHITESPACE, ( $stackPtr + 1 ), null, true ); + $snippet = $this->get_snippet( $tokens[ $nextVar ]['content'] ); + $data = array( + $snippet, + $content, + $snippet, + ); + + $closer = $this->find_closing_tag( $phpcsFile, $tokens, $stackPtr, '%>' ); + + if ( false === $closer ) { + $phpcsFile->addError( $error, $stackPtr, 'ASPShortOpenTagFound', $data ); + } else { + $fix = $phpcsFile->addFixableError( $error, $stackPtr, 'ASPShortOpenTagFound', $data ); + if ( true === $fix ) { + $this->add_changeset( $phpcsFile, $tokens, $stackPtr, $closer, true ); + } + } + + return; + } + + // Account for incorrect script open tags. The "(?:]+)?language=[\'"]?php[\'"]?(?:[^>]+)?>)`i', $content, $match ) ) { + $error = 'Script style opening tag used; expected "get_snippet( $content, $match[1] ); + $data = array( $match[1] . $snippet ); + + $phpcsFile->addError( $error, $stackPtr, 'ScriptOpenTagFound', $data ); + + return; + } + + if ( T_INLINE_HTML === $openTag['code'] && false === $this->asp_tags ) { + if ( false !== strpos( $content, '<%=' ) ) { + $error = 'Possible use of ASP style short opening tags detected. Needs manual inspection. Found: %s'; + $snippet = $this->get_snippet( $content, '<%=' ); + $data = array( '<%=' . $snippet ); + + $phpcsFile->addWarning( $error, $stackPtr, 'MaybeASPShortOpenTagFound', $data ); + + } elseif ( false !== strpos( $content, '<%' ) ) { + $error = 'Possible use of ASP style opening tags detected. Needs manual inspection. Found: %s'; + $snippet = $this->get_snippet( $content, '<%' ); + $data = array( '<%' . $snippet ); + + $phpcsFile->addWarning( $error, $stackPtr, 'MaybeASPOpenTagFound', $data ); + } + } + } // end process() + + /** + * Get a snippet from a HTML token. + * + * @param string $content The content of the HTML token. + * @param string $start_at Partial string to use as a starting point for the snippet. + * @param int $length The target length of the snippet to get. Defaults to 40. + * @return string + */ + private function get_snippet( $content, $start_at = '', $length = 40 ) { + $start_pos = 0; + + if ( '' !== $start_at ) { + $start_pos = strpos( $content, $start_at ); + if ( false !== $start_pos ) { + $start_pos += strlen( $start_at ); + } + } + + $snippet = substr( $content, $start_pos, $length ); + if ( ( strlen( $content ) - $start_pos ) > $length ) { + $snippet .= '...'; + } + + return $snippet; + } + + /** + * Try and find a matching PHP closing tag. + * + * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param array $tokens The token stack. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param string $content The expected content of the closing tag to match the opener. + * @return int|false Pointer to the position in the stack for the closing tag or false if not found. + */ + private function find_closing_tag( PHP_CodeSniffer_File $phpcsFile, $tokens, $stackPtr, $content ) { + $closer = $phpcsFile->findNext( T_CLOSE_TAG, ( $stackPtr + 1 ) ); + + if ( false !== $closer && trim( $tokens[ $closer ]['content'] ) === $content ) { + return $closer; + } + + return false; + } + + /** + * Add a changeset to replace the alternative PHP tags. + * + * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param array $tokens The token stack. + * @param int $open_tag_pointer Stack pointer to the PHP open tag. + * @param int $close_tag_pointer Stack pointer to the PHP close tag. + * @param bool $echo Whether to add 'echo' or not. + */ + private function add_changeset( PHP_CodeSniffer_File $phpcsFile, $tokens, $open_tag_pointer, $close_tag_pointer, $echo = false ) { + // Build up the open tag replacement and make sure there's always whitespace behind it. + $open_replacement = '', $tokens[ $close_tag_pointer ]['content'] ); + + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken( $open_tag_pointer, $open_replacement ); + $phpcsFile->fixer->replaceToken( $close_tag_pointer, $close_replacement ); + $phpcsFile->fixer->endChangeset(); + } + +} // End class. diff --git a/WordPress/Sniffs/PHP/DiscouragedFunctionsSniff.php b/WordPress/Sniffs/PHP/DiscouragedFunctionsSniff.php index a1f1c03dbf..f6a01c5e41 100644 --- a/WordPress/Sniffs/PHP/DiscouragedFunctionsSniff.php +++ b/WordPress/Sniffs/PHP/DiscouragedFunctionsSniff.php @@ -1,50 +1,46 @@ + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ -if (class_exists('Generic_Sniffs_PHP_ForbiddenFunctionsSniff', true) === false) { - throw new PHP_CodeSniffer_Exception('Class Generic_Sniffs_PHP_ForbiddenFunctionsSniff not found'); +if ( ! class_exists( 'Generic_Sniffs_PHP_ForbiddenFunctionsSniff', true ) ) { + throw new PHP_CodeSniffer_Exception( 'Class Generic_Sniffs_PHP_ForbiddenFunctionsSniff not found' ); } /** - * WordPress_Sniffs_PHP_DiscouragedFunctionsSniff. + * Discourages the use of various functions and suggests (WordPress) alternatives. * - * Discourages the use of debug functions and suggests deprecated WordPress alternatives + * @package WPCS\WordPressCodingStandards * - * @category PHP - * @package PHP_CodeSniffer - * @author John Godley + * @since 0.1.0 + * @since 0.10.0 The checks for the POSIX functions have been replaced by the stand-alone + * sniff WordPress_Sniffs_PHP_POSIXFunctionsSniff. */ -class WordPress_Sniffs_PHP_DiscouragedFunctionsSniff extends Generic_Sniffs_PHP_ForbiddenFunctionsSniff -{ +class WordPress_Sniffs_PHP_DiscouragedFunctionsSniff extends Generic_Sniffs_PHP_ForbiddenFunctionsSniff { - /** - * A list of forbidden functions with their alternatives. - * - * The value is NULL if no alternative exists. IE, the - * function should just not be used. - * - * @var array(string => string|null) - */ - public $forbiddenFunctions = array( + /** + * A list of forbidden functions with their alternatives. + * + * The value is NULL if no alternative exists. I.e. the + * function should just not be used. + * + * @var array(string => string|null) + */ + public $forbiddenFunctions = array( + // Development. 'print_r' => null, 'debug_print_backtrace' => null, - 'ereg_replace' => 'preg_replace', - 'ereg' => null, - 'eregi_replace' => 'preg_replace', - 'json_encode' => 'wp_json_encode', - 'split' => null, - 'spliti' => null, 'var_dump' => null, 'var_export' => null, - // WordPress + + // Discouraged. + 'json_encode' => 'wp_json_encode', + + // WordPress deprecated. 'find_base_dir' => 'WP_Filesystem::abspath', 'get_base_dir' => 'WP_Filesystem::abspath', 'dropdown_categories' => 'wp_link_category_checklist', @@ -59,17 +55,37 @@ class WordPress_Sniffs_PHP_DiscouragedFunctionsSniff extends Generic_Sniffs_PHP_ 'get_attachment_icon_src' => 'wp_get_attachment_image_src', 'get_attachment_icon' => 'wp_get_attachment_image', 'get_attachment_innerHTML' => 'wp_get_attachment_image', + + // WordPress discouraged. 'query_posts' => 'WP_Query', 'wp_reset_query' => 'wp_reset_postdata', ); - /** - * If true, an error will be thrown; otherwise a warning. - * - * @var bool - */ - public $error = false; + /** + * If true, an error will be thrown; otherwise a warning. + * + * @var bool + */ + public $error = false; + + /** + * Returns an array of tokens this test wants to listen for. + * + * {@internal Temporarily overrule the parent register() method until bugfix has + * been merged into PHPCS upstream and WPCS minimum PHPCS version has caught up. + * {@link https://github.com/squizlabs/PHP_CodeSniffer/pull/1076} }} + * + * @return array + */ + public function register() { + $register = parent::register(); + + if ( true !== $this->patternMatch ) { + $this->forbiddenFunctionNames = array_map( 'strtolower', $this->forbiddenFunctionNames ); + $this->forbiddenFunctions = array_combine( $this->forbiddenFunctionNames, $this->forbiddenFunctions ); + } -}//end class + return $register; + } -?> +} // End class. diff --git a/WordPress/Sniffs/PHP/POSIXFunctionsSniff.php b/WordPress/Sniffs/PHP/POSIXFunctionsSniff.php new file mode 100644 index 0000000000..8a78541c70 --- /dev/null +++ b/WordPress/Sniffs/PHP/POSIXFunctionsSniff.php @@ -0,0 +1,70 @@ + array( + * 'lambda' => array( + * 'type' => 'error' | 'warning', + * 'message' => 'Use anonymous functions instead please!', + * 'functions' => array( 'eval', 'create_function' ), + * ) + * ) + * + * @return array + */ + public function getGroups() { + return array( + 'ereg' => array( + 'type' => 'error', + 'message' => '%s has been deprecated since PHP 5.3 and removed in PHP 7.0, please use preg_match() instead.', + 'functions' => array( + 'ereg', + 'eregi', + 'sql_regcase', + ), + ), + + 'ereg_replace' => array( + 'type' => 'error', + 'message' => '%s has been deprecated since PHP 5.3 and removed in PHP 7.0, please use preg_replace() instead.', + 'functions' => array( + 'ereg_replace', + 'eregi_replace', + ), + ), + + 'split' => array( + 'type' => 'error', + 'message' => '%s has been deprecated since PHP 5.3 and removed in PHP 7.0, please use explode(), str_split() or preg_split() instead.', + 'functions' => array( + 'split', + 'spliti', + ), + ), + + ); + } // end getGroups() + +} // End class. diff --git a/WordPress/Sniffs/PHP/StrictComparisonsSniff.php b/WordPress/Sniffs/PHP/StrictComparisonsSniff.php index e7126ec4f5..0386e801f0 100644 --- a/WordPress/Sniffs/PHP/StrictComparisonsSniff.php +++ b/WordPress/Sniffs/PHP/StrictComparisonsSniff.php @@ -1,51 +1,56 @@ init( $phpcsFile ); if ( ! $this->has_whitelist_comment( 'loose comparison', $stackPtr ) ) { - $tokens = $phpcsFile->getTokens(); - $error = 'Found: ' . $tokens[$stackPtr]['content'] . '. Use strict comparisons (=== or !==).'; + $error = 'Found: ' . $this->tokens[ $stackPtr ]['content'] . '. Use strict comparisons (=== or !==).'; $phpcsFile->addWarning( $error, $stackPtr, 'LooseComparison' ); } - }//end process() + } -}//end class +} // End class. diff --git a/WordPress/Sniffs/PHP/StrictInArraySniff.php b/WordPress/Sniffs/PHP/StrictInArraySniff.php index d14bc307b3..2ef72fb9ad 100644 --- a/WordPress/Sniffs/PHP/StrictInArraySniff.php +++ b/WordPress/Sniffs/PHP/StrictInArraySniff.php @@ -1,13 +1,47 @@ => + */ + protected $array_functions = array( + 'in_array' => true, + 'array_search' => true, + 'array_keys' => false, + ); /** * Returns an array of tokens this test wants to listen for. @@ -23,32 +57,43 @@ public function register() { /** * Processes this test, when one of its tokens is encountered. * - * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. - * @param int $stackPtr The position of the current token in the stack passed in $tokens. + * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. * * @return void */ public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) { $tokens = $phpcsFile->getTokens(); + $token = strtolower( $tokens[ $stackPtr ]['content'] ); - // Skip any token that is not 'in_array'. - if ( 'in_array' !== strtolower( $tokens[ $stackPtr ]['content'] ) ) { + // Bail out if not one of the targetted functions. + if ( ! isset( $this->array_functions[ $token ] ) ) { return; } - if ( ! isset( $tokens[ $stackPtr - 1 ] ) ) { + if ( ! isset( $tokens[ ( $stackPtr - 1 ) ] ) ) { return; } - $prevToken = $phpcsFile->findPrevious( array( T_WHITESPACE, T_COMMENT ), ( $stackPtr - 1 ), null, true ); + $prev = $phpcsFile->findPrevious( PHP_CodeSniffer_Tokens::$emptyTokens, ( $stackPtr - 1 ), null, true ); - // Skip if this is instance of in_array() not a function call. - if ( false === $prevToken || in_array( $tokens[ $prevToken ]['code'], array( T_OBJECT_OPERATOR, T_DOUBLE_COLON ), true ) ) { - return; + if ( false !== $prev ) { + // Skip sniffing if calling a same-named method, or on function definitions. + if ( in_array( $tokens[ $prev ]['code'], array( T_FUNCTION, T_DOUBLE_COLON, T_OBJECT_OPERATOR ), true ) ) { + return; + } + + // Skip namespaced functions, ie: \foo\bar() not \bar(). + $pprev = $phpcsFile->findPrevious( PHP_CodeSniffer_Tokens::$emptyTokens, ( $prev - 1 ), null, true ); + if ( false !== $pprev && T_NS_SEPARATOR === $tokens[ $prev ]['code'] && T_STRING === $tokens[ $pprev ]['code'] ) { + return; + } } + unset( $prev, $pprev ); // Get the closing parenthesis. - $openParenthesis = $phpcsFile->findNext( T_OPEN_PARENTHESIS, $stackPtr + 1 ); + $openParenthesis = $phpcsFile->findNext( T_OPEN_PARENTHESIS, ( $stackPtr + 1 ) ); if ( false === $openParenthesis ) { return; } @@ -61,15 +106,27 @@ public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) { // Get last token in the function call. $closeParenthesis = $tokens[ $openParenthesis ]['parenthesis_closer']; - $lastToken = $phpcsFile->findPrevious( array( T_WHITESPACE, T_COMMENT ), $closeParenthesis - 1, $openParenthesis + 1, true ); + $lastToken = $phpcsFile->findPrevious( PHP_CodeSniffer_Tokens::$emptyTokens, ( $closeParenthesis - 1 ), ( $openParenthesis + 1 ), true ); + + // Check if the strict check is actually needed. + if ( false === $this->array_functions[ $token ] ) { + $hasComma = $phpcsFile->findPrevious( T_COMMA, ( $closeParenthesis - 1 ), ( $openParenthesis + 1 ) ); + if ( false === $hasComma || end( $tokens[ $hasComma ]['nested_parenthesis'] ) !== $closeParenthesis ) { + return; + } + } + + $errorData = array( $token ); + if ( false === $lastToken ) { - $phpcsFile->addError( 'Missing arguments to in_array().', $openParenthesis, 'MissingArguments' ); + $phpcsFile->addError( 'Missing arguments to %s.', $openParenthesis, 'MissingArguments', $errorData ); return; } if ( T_TRUE !== $tokens[ $lastToken ]['code'] ) { - $phpcsFile->addWarning( 'Not using strict comparison for in_array(); supply true for third argument.', $lastToken, 'MissingTrueStrict' ); + $phpcsFile->addWarning( 'Not using strict comparison for %s; supply true for third argument.', $lastToken, 'MissingTrueStrict', $errorData ); return; } - } -} + } // end process() + +} // End class. diff --git a/WordPress/Sniffs/PHP/YodaConditionsSniff.php b/WordPress/Sniffs/PHP/YodaConditionsSniff.php index 922761dadb..f7ba541aad 100644 --- a/WordPress/Sniffs/PHP/YodaConditionsSniff.php +++ b/WordPress/Sniffs/PHP/YodaConditionsSniff.php @@ -1,33 +1,29 @@ - * @author Greg Sherwood - * @author Marc McIntyre + * @since 0.3.0 */ -class WordPress_Sniffs_PHP_YodaConditionsSniff implements PHP_CodeSniffer_Sniff -{ +class WordPress_Sniffs_PHP_YodaConditionsSniff implements PHP_CodeSniffer_Sniff { /** * Returns an array of tokens this test wants to listen for. * * @return array */ - public function register() - { + public function register() { return array( T_IS_EQUAL, T_IS_NOT_EQUAL, @@ -35,20 +31,18 @@ public function register() T_IS_NOT_IDENTICAL, ); - }//end register() - + } /** * Processes this test, when one of its tokens is encountered. * - * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. - * @param int $stackPtr The position of the current token in the - * stack passed in $tokens. + * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. * * @return void */ - public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) - { + public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) { $tokens = $phpcsFile->getTokens(); $beginners = array_merge( @@ -64,7 +58,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) for ( $i = $stackPtr; $i > $beginning; $i-- ) { // Ignore whitespace. - if ( in_array( $tokens[ $i ]['code'], PHP_CodeSniffer_Tokens::$emptyTokens ) ) { + if ( in_array( $tokens[ $i ]['code'], PHP_CodeSniffer_Tokens::$emptyTokens, true ) ) { continue; } @@ -75,7 +69,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) } // If this is a function call or something, we are OK. - if ( in_array( $tokens[ $i ]['code'], array( T_CONSTANT_ENCAPSED_STRING, T_CLOSE_PARENTHESIS, T_OPEN_PARENTHESIS, T_RETURN ) ) ) { + if ( in_array( $tokens[ $i ]['code'], array( T_CONSTANT_ENCAPSED_STRING, T_CLOSE_PARENTHESIS, T_OPEN_PARENTHESIS, T_RETURN ), true ) ) { return; } } @@ -84,17 +78,17 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) return; } - // Check if this is a var to var comparison, e.g.: if ( $var1 == $var2 ) - $next_non_empty = $phpcsFile->findNext( PHP_CodeSniffer_Tokens::$emptyTokens, $stackPtr + 1, null, true ); + // Check if this is a var to var comparison, e.g.: if ( $var1 == $var2 ). + $next_non_empty = $phpcsFile->findNext( PHP_CodeSniffer_Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true ); - if ( in_array( $tokens[ $next_non_empty ]['code'], PHP_CodeSniffer_Tokens::$castTokens ) ) { - $next_non_empty = $phpcsFile->findNext( PHP_CodeSniffer_Tokens::$emptyTokens, $next_non_empty + 1, null, true ); + if ( in_array( $tokens[ $next_non_empty ]['code'], PHP_CodeSniffer_Tokens::$castTokens, true ) ) { + $next_non_empty = $phpcsFile->findNext( PHP_CodeSniffer_Tokens::$emptyTokens, ( $next_non_empty + 1 ), null, true ); } - if ( in_array( $tokens[ $next_non_empty ]['code'], array( T_SELF, T_PARENT, T_STATIC ) ) ) { + if ( in_array( $tokens[ $next_non_empty ]['code'], array( T_SELF, T_PARENT, T_STATIC ), true ) ) { $next_non_empty = $phpcsFile->findNext( array_merge( PHP_CodeSniffer_Tokens::$emptyTokens, array( T_DOUBLE_COLON ) ) - , $next_non_empty + 1 + , ( $next_non_empty + 1 ) , null , true ); @@ -106,9 +100,6 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) $phpcsFile->addError( 'Use Yoda Condition checks, you must', $stackPtr, 'NotYoda' ); - }//end process() - - -}//end class + } // end process() -?> +} // End class. diff --git a/WordPress/Sniffs/VIP/AdminBarRemovalSniff.php b/WordPress/Sniffs/VIP/AdminBarRemovalSniff.php index b8f9f48e99..f2a7083983 100644 --- a/WordPress/Sniffs/VIP/AdminBarRemovalSniff.php +++ b/WordPress/Sniffs/VIP/AdminBarRemovalSniff.php @@ -1,30 +1,36 @@ + * @link https://vip.wordpress.com/documentation/vip/code-review-what-we-look-for/#removing-the-admin-bar + * + * @package WPCS\WordPressCodingStandards + * + * @since 0.3.0 */ -class WordPress_Sniffs_VIP_AdminBarRemovalSniff implements PHP_CodeSniffer_Sniff -{ +class WordPress_Sniffs_VIP_AdminBarRemovalSniff implements PHP_CodeSniffer_Sniff { /** * Returns an array of tokens this test wants to listen for. * * @return array */ - public function register() - { + public function register() { return array( - T_STRING, - T_CONSTANT_ENCAPSED_STRING, - T_DOUBLE_QUOTED_STRING, - ); - - }//end register() + T_STRING, + T_CONSTANT_ENCAPSED_STRING, + T_DOUBLE_QUOTED_STRING, + ); + } /** * Processes this test, when one of its tokens is encountered. @@ -35,16 +41,12 @@ public function register() * * @return void */ - public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) - { + public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) { $tokens = $phpcsFile->getTokens(); - if ( in_array( trim( $tokens[$stackPtr]['content'], '"\'' ), array( 'show_admin_bar' ) ) ) { - $phpcsFile->addError( 'Removal of admin bar is prohibited.', $stackPtr, 'RemovalDetected'); + if ( in_array( trim( $tokens[ $stackPtr ]['content'], '"\'' ), array( 'show_admin_bar' ), true ) ) { + $phpcsFile->addError( 'Removal of admin bar is prohibited.', $stackPtr, 'RemovalDetected' ); } - }//end process() - - -}//end class + } // end process() -?> +} // End class. diff --git a/WordPress/Sniffs/VIP/CronIntervalSniff.php b/WordPress/Sniffs/VIP/CronIntervalSniff.php index 1cde15ce31..6cec70acf7 100644 --- a/WordPress/Sniffs/VIP/CronIntervalSniff.php +++ b/WordPress/Sniffs/VIP/CronIntervalSniff.php @@ -1,28 +1,35 @@ + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ -class WordPress_Sniffs_VIP_CronIntervalSniff implements PHP_CodeSniffer_Sniff -{ + +/** + * Flag cron schedules less than 15 minutes. + * + * @link https://vip.wordpress.com/documentation/vip/code-review-what-we-look-for/#cron-schedules-less-than-15-minutes-or-expensive-events + * + * @package WPCS\WordPressCodingStandards + * + * @since 0.3.0 + */ +class WordPress_Sniffs_VIP_CronIntervalSniff implements PHP_CodeSniffer_Sniff { /** * Returns an array of tokens this test wants to listen for. * * @return array */ - public function register() - { + public function register() { return array( T_CONSTANT_ENCAPSED_STRING, T_DOUBLE_QUOTED_STRING, ); - }//end register() - + } /** * Processes this test, when one of its tokens is encountered. @@ -33,33 +40,32 @@ public function register() * * @return void */ - public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) - { + public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) { $tokens = $phpcsFile->getTokens(); - $token = $tokens[$stackPtr]; + $token = $tokens[ $stackPtr ]; - if ( 'cron_schedules' != trim( $token['content'], '"\'' ) ) { + if ( 'cron_schedules' !== trim( $token['content'], '"\'' ) ) { return; } - // If within add_filter + // If within add_filter. $functionPtr = $phpcsFile->findPrevious( T_STRING, key( $token['nested_parenthesis'] ) ); - if ( $tokens[$functionPtr]['content'] != 'add_filter' ) { + if ( 'add_filter' !== $tokens[ $functionPtr ]['content'] ) { return; } - // Detect callback function name - $callbackPtr = $phpcsFile->findNext( array( T_COMMA, T_WHITESPACE ), $stackPtr + 1, null, true, null, true ); + // Detect callback function name. + $callbackPtr = $phpcsFile->findNext( array( T_COMMA, T_WHITESPACE ), ( $stackPtr + 1 ), null, true, null, true ); - // If callback is array, get second element - if ( T_ARRAY === $tokens[$callbackPtr]['code'] ) { - $comma = $phpcsFile->findNext( T_COMMA, $callbackPtr + 1 ); + // If callback is array, get second element. + if ( T_ARRAY === $tokens[ $callbackPtr ]['code'] ) { + $comma = $phpcsFile->findNext( T_COMMA, ( $callbackPtr + 1 ) ); if ( false === $comma ) { $this->confused( $phpcsFile, $stackPtr ); return; } - $callbackPtr = $phpcsFile->findNext( array( T_WHITESPACE ), $comma + 1, null, true, null, true ); + $callbackPtr = $phpcsFile->findNext( array( T_WHITESPACE ), ( $comma + 1 ), null, true, null, true ); if ( false === $callbackPtr ) { $this->confused( $phpcsFile, $stackPtr ); return; @@ -68,18 +74,16 @@ public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) $functionPtr = null; - // Search for the function in tokens - if ( in_array( $tokens[$callbackPtr]['code'], array( T_CONSTANT_ENCAPSED_STRING, T_DOUBLE_QUOTED_STRING ) ) ) { - $functionName = trim( $tokens[$callbackPtr]['content'], '"\'' ); + // Search for the function in tokens. + if ( in_array( $tokens[ $callbackPtr ]['code'], array( T_CONSTANT_ENCAPSED_STRING, T_DOUBLE_QUOTED_STRING ), true ) ) { + $functionName = trim( $tokens[ $callbackPtr ]['content'], '"\'' ); foreach ( $tokens as $ptr => $_token ) { - if ( $_token['code'] == T_STRING && $_token['content'] == $functionName ) { + if ( T_STRING === $_token['code'] && $_token['content'] === $functionName ) { $functionPtr = $ptr; } } - } - // Closure - else if ( $tokens[$callbackPtr]['code'] === T_CLOSURE ) { + } elseif ( T_CLOSURE === $tokens[ $callbackPtr ]['code'] ) { // Closure. $functionPtr = $callbackPtr; } @@ -92,16 +96,16 @@ public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) $closing = $tokens[ $opening ]['bracket_closer']; for ( $i = $opening; $i <= $closing; $i++ ) { - if ( in_array( $tokens[$i]['code'], array( T_CONSTANT_ENCAPSED_STRING, T_DOUBLE_QUOTED_STRING ) ) ) { - if ( trim( $tokens[$i]['content'], '\'"' ) == 'interval' ) { + if ( in_array( $tokens[ $i ]['code'], array( T_CONSTANT_ENCAPSED_STRING, T_DOUBLE_QUOTED_STRING ), true ) ) { + if ( 'interval' === trim( $tokens[ $i ]['content'], '\'"' ) ) { $operator = $phpcsFile->findNext( T_DOUBLE_ARROW, $i, null, null, null, true ); if ( empty( $operator ) ) { $this->confused( $phpcsFile, $stackPtr ); } - $valueStart = $phpcsFile->findNext( T_WHITESPACE, $operator + 1, null, true, null, true ); - $valueEnd = $phpcsFile->findNext( array( T_COMMA, T_CLOSE_PARENTHESIS ), $valueStart + 1 ); - $value = $phpcsFile->getTokensAsString( $valueStart, $valueEnd - $valueStart ); + $valueStart = $phpcsFile->findNext( T_WHITESPACE, ( $operator + 1 ), null, true, null, true ); + $valueEnd = $phpcsFile->findNext( array( T_COMMA, T_CLOSE_PARENTHESIS ), ( $valueStart + 1 ) ); + $value = $phpcsFile->getTokensAsString( $valueStart, ( $valueEnd - $valueStart ) ); if ( is_numeric( $value ) ) { $interval = $value; @@ -110,7 +114,7 @@ public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) // If all digits and operators, eval! if ( preg_match( '#^[\s\d\+\*\-\/]+$#', $value ) > 0 ) { - $interval = eval( "return ( $value );" ); // No harm here + $interval = eval( "return ( $value );" ); // No harm here. break; } @@ -125,13 +129,21 @@ public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) return; } + } // end process() - }//end process() - - - public function confused( $phpcsFile, $stackPtr ) { - $phpcsFile->addWarning( 'Detected changing of cron_schedules, but could not detect the interval value.', $stackPtr, 'ChangeDetected' ); + /** + * Add warning about unclear cron schedule change. + * + * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + */ + public function confused( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) { + $phpcsFile->addWarning( + 'Detected changing of cron_schedules, but could not detect the interval value.', + $stackPtr, + 'ChangeDetected' + ); } - -}//end class +} // End class. diff --git a/WordPress/Sniffs/VIP/DirectDatabaseQuerySniff.php b/WordPress/Sniffs/VIP/DirectDatabaseQuerySniff.php index 9d131630da..73a4c0d860 100644 --- a/WordPress/Sniffs/VIP/DirectDatabaseQuerySniff.php +++ b/WordPress/Sniffs/VIP/DirectDatabaseQuerySniff.php @@ -1,16 +1,24 @@ - * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards/issues/69 + * @since 0.3.0 + * @since 0.6.0 Removed the add_unique_message() function as it is no longer needed. */ -class WordPress_Sniffs_VIP_DirectDatabaseQuerySniff implements PHP_CodeSniffer_Sniff -{ +class WordPress_Sniffs_VIP_DirectDatabaseQuerySniff implements PHP_CodeSniffer_Sniff { /** * List of custom cache get functions. @@ -67,14 +75,12 @@ class WordPress_Sniffs_VIP_DirectDatabaseQuerySniff implements PHP_CodeSniffer_S * * @return array */ - public function register() - { + public function register() { return array( - T_VARIABLE, - ); - - }//end register() + T_VARIABLE, + ); + } /** * Processes this test, when one of its tokens is encountered. @@ -85,8 +91,7 @@ public function register() * * @return int|void */ - public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) - { + public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) { if ( ! isset( self::$methods['all'] ) ) { self::$methods['all'] = array_merge( self::$methods['cachable'], self::$methods['noncachable'] ); @@ -108,49 +113,51 @@ public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) $tokens = $phpcsFile->getTokens(); - // Check for $wpdb variable - if ( $tokens[$stackPtr]['content'] != '$wpdb' ) + // Check for $wpdb variable. + if ( '$wpdb' !== $tokens[ $stackPtr ]['content'] ) { return; + } - $is_object_call = $phpcsFile->findNext( array( T_OBJECT_OPERATOR ), $stackPtr + 1, null, null, null, true ); - if ( false == $is_object_call ) - return; // This is not a call to the wpdb object + $is_object_call = $phpcsFile->findNext( array( T_OBJECT_OPERATOR ), ( $stackPtr + 1 ), null, null, null, true ); + if ( false === $is_object_call ) { + return; // This is not a call to the wpdb object. + } - $methodPtr = $phpcsFile->findNext( array( T_WHITESPACE ), $is_object_call + 1, null, true, null, true ); - $method = $tokens[ $methodPtr ]['content']; + $methodPtr = $phpcsFile->findNext( array( T_WHITESPACE ), ( $is_object_call + 1 ), null, true, null, true ); + $method = $tokens[ $methodPtr ]['content']; if ( ! isset( self::$methods['all'][ $method ] ) ) { return; } - $endOfStatement = $phpcsFile->findNext( array( T_SEMICOLON ), $stackPtr + 1, null, null, null, true ); + $endOfStatement = $phpcsFile->findNext( array( T_SEMICOLON ), ( $stackPtr + 1 ), null, null, null, true ); $endOfLineComment = ''; - for ( $i = $endOfStatement + 1; $i < count( $tokens ); $i++ ) { + $tokenCount = count( $tokens ); + for ( $i = ( $endOfStatement + 1 ); $i < $tokenCount; $i++ ) { - if ( $tokens[$i]['line'] !== $tokens[$endOfStatement]['line'] ) { + if ( $tokens[ $i ]['line'] !== $tokens[ $endOfStatement ]['line'] ) { break; } - if ( $tokens[$i]['code'] === T_COMMENT ) { - $endOfLineComment .= $tokens[$i]['content']; + if ( T_COMMENT === $tokens[ $i ]['code'] ) { + $endOfLineComment .= $tokens[ $i ]['content']; } - } $whitelisted_db_call = false; - if ( preg_match( '/db call\W*(ok|pass|clear|whitelist)/i', $endOfLineComment, $matches ) ) { + if ( preg_match( '/db call\W*(?:ok|pass|clear|whitelist)/i', $endOfLineComment ) ) { $whitelisted_db_call = true; } - // Check for Database Schema Changes + // Check for Database Schema Changes. $_pos = $stackPtr; - while ( $_pos = $phpcsFile->findNext( array( T_CONSTANT_ENCAPSED_STRING, T_DOUBLE_QUOTED_STRING ), $_pos + 1, $endOfStatement, null, null, true ) ) { - if ( preg_match( '#\b(ALTER|CREATE|DROP)\b#i', $tokens[$_pos]['content'], $matches ) > 0 ) { + while ( $_pos = $phpcsFile->findNext( array( T_CONSTANT_ENCAPSED_STRING, T_DOUBLE_QUOTED_STRING ), ( $_pos + 1 ), $endOfStatement, null, null, true ) ) { + if ( preg_match( '#\b(?:ALTER|CREATE|DROP)\b#i', $tokens[ $_pos ]['content'] ) > 0 ) { $phpcsFile->addError( 'Attempting a database schema change is highly discouraged.', $_pos, 'SchemaChange' ); } } - // Flag instance if not whitelisted + // Flag instance if not whitelisted. if ( ! $whitelisted_db_call ) { $phpcsFile->addWarning( 'Usage of a direct database call is discouraged.', $stackPtr, 'DirectQuery' ); } @@ -160,27 +167,26 @@ public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) } $whitelisted_cache = false; - $cached = $wp_cache_get = false; - if ( preg_match( '/cache\s+(ok|pass|clear|whitelist)/i', $endOfLineComment, $matches ) ) { + $cached = $wp_cache_get = false; + if ( preg_match( '/cache\s+(?:ok|pass|clear|whitelist)/i', $endOfLineComment ) ) { $whitelisted_cache = true; } - if ( ! $whitelisted_cache && ! empty( $tokens[$stackPtr]['conditions'] ) ) { + if ( ! $whitelisted_cache && ! empty( $tokens[ $stackPtr ]['conditions'] ) ) { $scope_function = $phpcsFile->getCondition( $stackPtr, T_FUNCTION ); if ( $scope_function ) { - $scopeStart = $tokens[$scope_function]['scope_opener']; - $scopeEnd = $tokens[$scope_function]['scope_closer']; + $scopeStart = $tokens[ $scope_function ]['scope_opener']; + $scopeEnd = $tokens[ $scope_function ]['scope_closer']; - for ( $i = $scopeStart + 1; $i < $scopeEnd; $i++ ) { + for ( $i = ( $scopeStart + 1 ); $i < $scopeEnd; $i++ ) { if ( T_STRING === $tokens[ $i ]['code'] ) { if ( isset( WordPress_Sniff::$cacheDeleteFunctions[ $tokens[ $i ]['content'] ] ) ) { - if ( in_array( $method, array( 'query', 'update', 'replace', 'delete' ) ) ) { + if ( in_array( $method, array( 'query', 'update', 'replace', 'delete' ), true ) ) { $cached = true; break; } - } elseif ( isset( WordPress_Sniff::$cacheGetFunctions[ $tokens[ $i ]['content'] ] ) ) { $wp_cache_get = true; @@ -204,6 +210,6 @@ public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) return $endOfStatement; - }//end process() + } // end process() -}//end class +} // End class. diff --git a/WordPress/Sniffs/VIP/FileSystemWritesDisallowSniff.php b/WordPress/Sniffs/VIP/FileSystemWritesDisallowSniff.php index 61a9ade3a0..674a077793 100644 --- a/WordPress/Sniffs/VIP/FileSystemWritesDisallowSniff.php +++ b/WordPress/Sniffs/VIP/FileSystemWritesDisallowSniff.php @@ -1,16 +1,26 @@ - * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards/issues/69 + * @link https://vip.wordpress.com/documentation/vip/code-review-what-we-look-for/#filesystem-writes + * + * @package WPCS\WordPressCodingStandards + * + * @since 0.3.0 */ -class WordPress_Sniffs_VIP_FileSystemWritesDisallowSniff extends Generic_Sniffs_PHP_ForbiddenFunctionsSniff -{ +class WordPress_Sniffs_VIP_FileSystemWritesDisallowSniff extends Generic_Sniffs_PHP_ForbiddenFunctionsSniff { /** * A list of forbidden functions with their alternatives. @@ -21,32 +31,32 @@ class WordPress_Sniffs_VIP_FileSystemWritesDisallowSniff extends Generic_Sniffs_ * @var array(string => string|null) */ public $forbiddenFunctions = array( - 'file_put_contents' => null, - 'fwrite' => null, - 'fputcsv' => null, - 'fputs' => null, - 'ftruncate' => null, - 'link' => null, - 'symlink' => null, - 'mkdir' => null, - 'rename' => null, - 'rmdir' => null, - 'tempnam' => null, - 'touch' => null, - 'unlink' => null, - 'is_writable' => null, - 'is_writeable' => null, - 'lchgrp' => null, - 'lchown' => null, - 'fputcsv' => null, - 'delete' => null, - 'chmod' => null, - 'chown' => null, - 'chgrp' => null, - 'chmod' => null, - 'chmod' => null, - 'flock' => null, - ); + 'file_put_contents' => null, + 'fwrite' => null, + 'fputcsv' => null, + 'fputs' => null, + 'ftruncate' => null, + 'link' => null, + 'symlink' => null, + 'mkdir' => null, + 'rename' => null, + 'rmdir' => null, + 'tempnam' => null, + 'touch' => null, + 'unlink' => null, + 'is_writable' => null, + 'is_writeable' => null, + 'lchgrp' => null, + 'lchown' => null, + 'fputcsv' => null, + 'delete' => null, + 'chmod' => null, + 'chown' => null, + 'chgrp' => null, + 'chmod' => null, + 'chmod' => null, + 'flock' => null, + ); /** * If true, an error will be thrown; otherwise a warning. @@ -58,6 +68,8 @@ class WordPress_Sniffs_VIP_FileSystemWritesDisallowSniff extends Generic_Sniffs_ /** * Generates the error or warning for this sniff. * + * Overloads parent addError method. + * * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. * @param int $stackPtr The position of the forbidden function * in the token array. @@ -66,18 +78,16 @@ class WordPress_Sniffs_VIP_FileSystemWritesDisallowSniff extends Generic_Sniffs_ * * @return void */ - protected function addError( $phpcsFile, $stackPtr, $function, $pattern = null ) - { - $data = array($function); + protected function addError( $phpcsFile, $stackPtr, $function, $pattern = null ) { + $data = array( $function ); $error = 'Filesystem writes are forbidden, you should not be using %s()'; - if ( $this->error === true ) { + if ( true === $this->error ) { $phpcsFile->addError( $error, $stackPtr, 'FileWriteDetected', $data ); } else { $phpcsFile->addWarning( $error, $stackPtr, 'FileWriteDetected', $data ); } - }//end addError() - + } -}//end class +} // End class. diff --git a/WordPress/Sniffs/VIP/OrderByRandSniff.php b/WordPress/Sniffs/VIP/OrderByRandSniff.php index 9e39d2da36..158a11312c 100644 --- a/WordPress/Sniffs/VIP/OrderByRandSniff.php +++ b/WordPress/Sniffs/VIP/OrderByRandSniff.php @@ -1,12 +1,22 @@ rand. * - * @link https://vip.wordpress.com/documentation/code-review-what-we-look-for/#order-by-rand - * @category PHP - * @package PHP_CodeSniffer + * @link https://vip.wordpress.com/documentation/code-review-what-we-look-for/#order-by-rand + * + * @package WPCS\WordPressCodingStandards + * + * @since 0.9.0 */ -class WordPress_Sniffs_VIP_OrderByRandSniff extends WordPress_Sniffs_Arrays_ArrayAssignmentRestrictionsSniff { +class WordPress_Sniffs_VIP_OrderByRandSniff extends WordPress_AbstractArrayAssignmentRestrictionsSniff { /** * Groups of variables to restrict. @@ -20,7 +30,7 @@ public function getGroups() { 'keys' => array( 'orderby', ), - ) + ), ); } @@ -28,11 +38,11 @@ public function getGroups() { * Callback to process each confirmed key, to check value * This must be extended to add the logic to check assignment value * - * @param string $key Array index / key - * @param mixed $val Assigned value - * @param int $line Token line - * @param array $group Group definition - * @return mixed FALSE if no match, TRUE if matches, STRING if matches with custom error message passed to ->process() + * @param string $key Array index / key. + * @param mixed $val Assigned value. + * @param int $line Token line. + * @param array $group Group definition. + * @return mixed FALSE if no match, TRUE if matches, STRING if matches with custom error message passed to ->process(). */ public function callback( $key, $val, $line, $group ) { if ( 'rand' === strtolower( $val ) ) { @@ -42,4 +52,4 @@ public function callback( $key, $val, $line, $group ) { } } -}//end class +} // End class. diff --git a/WordPress/Sniffs/VIP/PluginMenuSlugSniff.php b/WordPress/Sniffs/VIP/PluginMenuSlugSniff.php index 863d3da472..807cf2c24b 100644 --- a/WordPress/Sniffs/VIP/PluginMenuSlugSniff.php +++ b/WordPress/Sniffs/VIP/PluginMenuSlugSniff.php @@ -1,14 +1,28 @@ + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ -class WordPress_Sniffs_VIP_PluginMenuSlugSniff implements PHP_CodeSniffer_Sniff -{ +/** + * Warn about __FILE__ for page registration. + * + * @link https://vip.wordpress.com/documentation/vip/code-review-what-we-look-for/#using-__file__-for-page-registration + * + * @package WPCS\WordPressCodingStandards + * + * @since 0.3.0 + */ +class WordPress_Sniffs_VIP_PluginMenuSlugSniff implements PHP_CodeSniffer_Sniff { + + /** + * Functions which can be used to add pages to the WP Admin menu. + * + * @var array + */ public $add_menu_functions = array( 'add_menu_page', 'add_object_page', @@ -25,21 +39,19 @@ class WordPress_Sniffs_VIP_PluginMenuSlugSniff implements PHP_CodeSniffer_Sniff 'add_users_page', 'add_management_page', 'add_options_page', - ); + ); /** * Returns an array of tokens this test wants to listen for. * * @return array */ - public function register() - { + public function register() { return array( - T_STRING, - ); - - }//end register() + T_STRING, + ); + } /** * Processes this test, when one of its tokens is encountered. @@ -50,24 +62,23 @@ public function register() * * @return void */ - public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) - { + public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) { $tokens = $phpcsFile->getTokens(); - $token = $tokens[$stackPtr]; + $token = $tokens[ $stackPtr ]; - if ( ! in_array( $token['content'], $this->add_menu_functions ) ) { + if ( ! in_array( $token['content'], $this->add_menu_functions, true ) ) { return; } $opening = $phpcsFile->findNext( T_OPEN_PARENTHESIS, $stackPtr ); - $closing = $tokens[$opening]['parenthesis_closer']; + $closing = $tokens[ $opening ]['parenthesis_closer']; $string = $phpcsFile->findNext( T_FILE, $opening, $closing, null, '__FILE__', true ); if ( $string ) { $phpcsFile->addError( 'Using __FILE__ for menu slugs risks exposing filesystem structure.', $stackPtr, 'Using__FILE__' ); } - - }//end process() -}//end class + } + +} // End class. diff --git a/WordPress/Sniffs/VIP/PostsPerPageSniff.php b/WordPress/Sniffs/VIP/PostsPerPageSniff.php index ce01a3ae0a..fbc22a5a36 100644 --- a/WordPress/Sniffs/VIP/PostsPerPageSniff.php +++ b/WordPress/Sniffs/VIP/PostsPerPageSniff.php @@ -1,24 +1,33 @@ + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ -class WordPress_Sniffs_VIP_PostsPerPageSniff extends WordPress_Sniffs_Arrays_ArrayAssignmentRestrictionsSniff -{ + +/** + * Flag returning high or infinite posts_per_page. + * + * @link https://vip.wordpress.com/documentation/vip/code-review-what-we-look-for/#no-limit-queries + * + * @package WPCS\WordPressCodingStandards + * + * @since 0.3.0 + */ +class WordPress_Sniffs_VIP_PostsPerPageSniff extends WordPress_AbstractArrayAssignmentRestrictionsSniff { /** - * Groups of variables to restrict + * Groups of variables to restrict. * This should be overridden in extending classes. * * Example: groups => array( * 'wpdb' => array( - * 'type' => 'error' | 'warning', - * 'message' => 'Dont use this one please!', - * 'variables' => array( '$val', '$var' ), - * 'object_vars' => array( '$foo->bar', .. ), + * 'type' => 'error' | 'warning', + * 'message' => 'Dont use this one please!', + * 'variables' => array( '$val', '$var' ), + * 'object_vars' => array( '$foo->bar', .. ), * 'array_members' => array( '$foo['bar']', .. ), * ) * ) @@ -33,39 +42,38 @@ public function getGroups() { 'posts_per_page', 'nopaging', 'numberposts', - ), - ) - ); + ), + ), + ); } /** - * Callback to process each confirmed key, to check value - * This must be extended to add the logic to check assignment value - * - * @param string $key Array index / key - * @param mixed $val Assigned value - * @param int $line Token line - * @param array $group Group definition - * @return mixed FALSE if no match, TRUE if matches, STRING if matches with custom error message passed to ->process() + * Callback to process each confirmed key, to check value. + * This must be extended to add the logic to check assignment value. + * + * @param string $key Array index / key. + * @param mixed $val Assigned value. + * @param int $line Token line. + * @param array $group Group definition. + * @return mixed FALSE if no match, TRUE if matches, STRING if matches + * with custom error message passed to ->process(). */ public function callback( $key, $val, $line, $group ) { $key = strtolower( $key ); if ( - ( $key == 'nopaging' && ( $val == 'true' || $val == 1 ) ) + ( 'nopaging' === $key && ( 'true' === $val || 1 === $val ) ) || - ( in_array( $key, array( 'numberposts', 'posts_per_page' ) ) && $val == '-1' ) + ( in_array( $key, array( 'numberposts', 'posts_per_page' ), true ) && '-1' == $val ) ) { + return 'Disabling pagination is prohibited in VIP context, do not set `%s` to `%s` ever.'; - } - elseif ( - in_array( $key, array( 'posts_per_page', 'numberposts' ) ) - ) { - if ( $val > 50 ) { + } elseif ( in_array( $key, array( 'posts_per_page', 'numberposts' ), true ) ) { + + if ( $val > 100 ) { return 'Detected high pagination limit, `%s` is set to `%s`'; } } } - -}//end class +} // End class. diff --git a/WordPress/Sniffs/VIP/RestrictedFunctionsSniff.php b/WordPress/Sniffs/VIP/RestrictedFunctionsSniff.php index d7deb3c7ef..c7ad00b30b 100644 --- a/WordPress/Sniffs/VIP/RestrictedFunctionsSniff.php +++ b/WordPress/Sniffs/VIP/RestrictedFunctionsSniff.php @@ -1,21 +1,31 @@ + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ -class WordPress_Sniffs_VIP_RestrictedFunctionsSniff extends WordPress_Sniffs_Functions_FunctionRestrictionsSniff -{ + +/** + * Restricts usage of some functions in VIP context. + * + * @package WPCS\WordPressCodingStandards + * + * @since 0.3.0 + * @since 0.10.0 The checks for `extract()` and the POSIX functions have been replaced by + * the stand-alone sniffs WordPress_Sniffs_Functions_DontExtractSniff and + * WordPress_Sniffs_PHP_POSIXFunctionsSniff respectively. + */ +class WordPress_Sniffs_VIP_RestrictedFunctionsSniff extends WordPress_AbstractFunctionRestrictionsSniff { /** - * Groups of functions to restrict + * Groups of functions to restrict. * * Example: groups => array( * 'lambda' => array( - * 'type' => 'error' | 'warning', - * 'message' => 'Use anonymous functions instead please!', + * 'type' => 'error' | 'warning', + * 'message' => 'Use anonymous functions instead please!', * 'functions' => array( 'eval', 'create_function' ), * ) * ) @@ -24,32 +34,34 @@ class WordPress_Sniffs_VIP_RestrictedFunctionsSniff extends WordPress_Sniffs_Fun */ public function getGroups() { return array( - + // @link https://vip.wordpress.com/documentation/vip/code-review-what-we-look-for/#switch_to_blog 'switch_to_blog' => array( 'type' => 'error', 'message' => '%s is not something you should ever need to do in a VIP theme context. Instead use an API (XML-RPC, REST) to interact with other sites if needed.', 'functions' => array( 'switch_to_blog' ), - ), + ), + // @link https://vip.wordpress.com/documentation/vip/code-review-what-we-look-for/#eval-and-create_function 'create_function' => array( - 'type' => 'warning', - 'message' => '%s is discouraged, please use Anonymous functions instead.', + 'type' => 'warning', + 'message' => '%s is discouraged, please use Anonymous functions instead.', 'functions' => array( 'create_function', ), ), + // @link https://vip.wordpress.com/documentation/vip/code-review-what-we-look-for/#eval-and-create_function 'eval' => array( - 'type' => 'error', - 'message' => '%s is prohibited, please use Anonymous functions instead.', + 'type' => 'error', + 'message' => '%s is prohibited, please use Anonymous functions instead.', 'functions' => array( 'eval', ), ), 'file_get_contents' => array( - 'type' => 'warning', - 'message' => '%s is highly discouraged, please use wpcom_vip_file_get_contents() instead.', + 'type' => 'warning', + 'message' => '%s is highly discouraged, please use wpcom_vip_file_get_contents() instead.', 'functions' => array( 'file_get_contents', 'vip_wp_file_get_contents', @@ -57,8 +69,8 @@ public function getGroups() { ), 'get_term_link' => array( - 'type' => 'error', - 'message' => '%s is prohibited, please use wpcom_vip_get_term_link() instead.', + 'type' => 'error', + 'message' => '%s is prohibited, please use wpcom_vip_get_term_link() instead.', 'functions' => array( 'get_term_link', 'get_tag_link', @@ -67,24 +79,24 @@ public function getGroups() { ), 'get_page_by_path' => array( - 'type' => 'error', - 'message' => '%s is prohibited, please use wpcom_vip_get_page_by_path() instead.', + 'type' => 'error', + 'message' => '%s is prohibited, please use wpcom_vip_get_page_by_path() instead.', 'functions' => array( 'get_page_by_path', ), ), 'get_page_by_title' => array( - 'type' => 'error', - 'message' => '%s is prohibited, please use wpcom_vip_get_page_by_title() instead.', + 'type' => 'error', + 'message' => '%s is prohibited, please use wpcom_vip_get_page_by_title() instead.', 'functions' => array( 'get_page_by_title', ), ), 'get_term_by' => array( - 'type' => 'error', - 'message' => '%s is prohibited, please use wpcom_vip_get_term_by() instead.', + 'type' => 'error', + 'message' => '%s is prohibited, please use wpcom_vip_get_term_by() instead.', 'functions' => array( 'get_term_by', 'get_cat_ID', @@ -92,16 +104,16 @@ public function getGroups() { ), 'get_category_by_slug' => array( - 'type' => 'error', - 'message' => '%s is prohibited, please use wpcom_vip_get_category_by_slug() instead.', + 'type' => 'error', + 'message' => '%s is prohibited, please use wpcom_vip_get_category_by_slug() instead.', 'functions' => array( 'get_category_by_slug', ), ), 'url_to_postid' => array( - 'type' => 'error', - 'message' => '%s is prohibited, please use wpcom_vip_url_to_postid() instead.', + 'type' => 'error', + 'message' => '%s is prohibited, please use wpcom_vip_url_to_postid() instead.', 'functions' => array( 'url_to_postid', 'url_to_post_id', @@ -109,86 +121,75 @@ public function getGroups() { ), 'attachment_url_to_postid' => array( - 'type' => 'error', - 'message' => '%s is prohibited, please use wpcom_vip_attachment_url_to_postid() instead.', + 'type' => 'error', + 'message' => '%s is prohibited, please use wpcom_vip_attachment_url_to_postid() instead.', 'functions' => array( 'attachment_url_to_postid', ), ), + // @link https://vip.wordpress.com/documentation/vip/code-review-what-we-look-for/#remote-calls 'wp_remote_get' => array( - 'type' => 'warning', - 'message' => '%s is highly discouraged, please use vip_safe_wp_remote_get() instead.', + 'type' => 'warning', + 'message' => '%s is highly discouraged, please use vip_safe_wp_remote_get() instead.', 'functions' => array( 'wp_remote_get', - ), ), + ), + // @link https://vip.wordpress.com/documentation/vip/code-review-what-we-look-for/#remote-calls 'curl' => array( - 'type' => 'warning', - 'message' => 'Using cURL functions is highly discouraged within VIP context. Check (Fetching Remote Data) on VIP Documentation.', + 'type' => 'warning', + 'message' => 'Using cURL functions is highly discouraged within VIP context. Check (Fetching Remote Data) on VIP Documentation.', 'functions' => array( 'curl_*', - ), - ), - - 'extract' => array( - 'type' => 'warning', - 'message' => '%s() usage is highly discouraged, due to the complexity and unintended issues it might cause.', - 'functions' => array( - 'extract', - ), ), + ), + // @link https://vip.wordpress.com/documentation/vip/code-review-what-we-look-for/#custom-roles 'custom_role' => array( - 'type' => 'error', - 'message' => 'Use wpcom_vip_add_role() instead of add_role()', + 'type' => 'error', + 'message' => 'Use wpcom_vip_add_role() instead of add_role()', 'functions' => array( 'add_role', - ), ), + ), + // @link https://vip.wordpress.com/documentation/vip/code-review-what-we-look-for/#caching-constraints 'cookies' => array( - 'type' => 'warning', - 'message' => 'Due to using Batcache, server side based client related logic will not work, use JS instead.', + 'type' => 'warning', + 'message' => 'Due to using Batcache, server side based client related logic will not work, use JS instead.', 'functions' => array( 'setcookie', - ), ), + ), + // @link https://vip.wordpress.com/documentation/vip/code-review-what-we-look-for/#working-with-wp_users-and-user_meta 'user_meta' => array( - 'type' => 'error', - 'message' => '%s() usage is highly discouraged, check VIP documentation on "Working with wp_users"', + 'type' => 'error', + 'message' => '%s() usage is highly discouraged, check VIP documentation on "Working with wp_users"', 'functions' => array( 'get_user_meta', 'update_user_meta', 'delete_user_meta', 'add_user_meta', - ), ), + ), // @todo Introduce a sniff specific to get_posts() that checks for suppress_filters=>false being supplied. 'get_posts' => array( - 'type' => 'warning', - 'message' => '%s is discouraged in favor of creating a new WP_Query() so that Advanced Post Cache will cache the query, unless you explicitly supply suppress_filters => false.', + 'type' => 'warning', + 'message' => '%s is discouraged in favor of creating a new WP_Query() so that Advanced Post Cache will cache the query, unless you explicitly supply suppress_filters => false.', 'functions' => array( 'get_posts', 'wp_get_recent_posts', - ), - ), - - 'get_pages' => array( - 'type' => 'error', - 'message' => '%s is highly discouraged in favor of creating a new WP_Query() so that Advanced Post Cache will cache the query.', - 'functions' => array( 'get_children', - 'get_pages', ), ), 'wp_get_post_terms' => array( - 'type' => 'error', - 'message' => '%s is highly discouraged due to not being cached; please use get_the_terms() along with wp_list_pluck() to extract the IDs.', + 'type' => 'error', + 'message' => '%s is highly discouraged due to not being cached; please use get_the_terms() along with wp_list_pluck() to extract the IDs.', 'functions' => array( 'wp_get_post_terms', 'wp_get_post_categories', @@ -198,47 +199,137 @@ public function getGroups() { ), 'term_exists' => array( - 'type' => 'error', - 'message' => '%s is highly discouraged due to not being cached; please use wpcom_vip_term_exists() instead.', + 'type' => 'error', + 'message' => '%s is highly discouraged due to not being cached; please use wpcom_vip_term_exists() instead.', 'functions' => array( 'term_exists', ), ), 'count_user_posts' => array( - 'type' => 'error', - 'message' => '%s is highly discouraged due to not being cached; please use wpcom_vip_count_user_posts() instead.', + 'type' => 'error', + 'message' => '%s is highly discouraged due to not being cached; please use wpcom_vip_count_user_posts() instead.', 'functions' => array( 'count_user_posts', ), ), 'wp_old_slug_redirect' => array( - 'type' => 'error', - 'message' => '%s is highly discouraged due to not being cached; please use wpcom_vip_old_slug_redirect() instead.', + 'type' => 'error', + 'message' => '%s is highly discouraged due to not being cached; please use wpcom_vip_old_slug_redirect() instead.', 'functions' => array( 'wp_old_slug_redirect', ), ), 'get_adjacent_post' => array( - 'type' => 'error', - 'message' => '%s is highly discouraged due to not being cached; please use wpcom_vip_get_adjacent_post() instead.', + 'type' => 'error', + 'message' => '%s is highly discouraged due to not being cached; please use wpcom_vip_get_adjacent_post() instead.', 'functions' => array( 'get_adjacent_post', 'get_previous_post', + 'get_previous_post_link', 'get_next_post', + 'get_next_post_link', ), ), + // @link https://vip.wordpress.com/documentation/vip/code-review-what-we-look-for/#use-wp_parse_url-instead-of-parse_url 'parse_url' => array( - 'type' => 'warning', - 'message' => '%s is discouraged due to a lack for backwards-compatibility in PHP versions; please use wp_parse_url() instead.', + 'type' => 'warning', + 'message' => '%s is discouraged due to a lack for backwards-compatibility in PHP versions; please use wp_parse_url() instead.', 'functions' => array( 'parse_url', ), ), + 'get_intermediate_image_sizes' => array( + 'type' => 'error', + 'message' => 'Intermediate images do not exist on the VIP platform, and thus get_intermediate_image_sizes() returns an empty array() on the platform. This behavior is intentional to prevent WordPress from generating multiple thumbnails when images are uploaded.', + 'functions' => array( + 'get_intermediate_image_sizes', + ), + ), + + // @link https://vip.wordpress.com/documentation/vip/code-review-what-we-look-for/#serializing-data + 'serialize' => array( + 'type' => 'warning', + 'message' => '%s Serialized data has known vulnerability problems with Object Injection. JSON is generally a better approach for serializing data.', + 'functions' => array( + 'serialize', + 'unserialize', + ), + ), + + // @link https://vip.wordpress.com/documentation/vip/code-review-what-we-look-for/#commented-out-code-debug-code-or-output + 'error_log' => array( + 'type' => 'error', + 'message' => '%s Debug code is not allowed on VIP Production', + 'functions' => array( + 'error_log', + 'var_dump', + 'print_r', + 'trigger_error', + 'set_error_handler', + ), + ), + + // @link https://vip.wordpress.com/documentation/vip/code-review-what-we-look-for/#use-wp_safe_redirect-instead-of-wp_redirect + 'wp_redirect' => array( + 'type' => 'warning', + 'message' => '%s Using wp_safe_redirect(), along with the allowed_redirect_hosts filter, can help avoid any chances of malicious redirects within code. It’s also important to remember to call exit() after a redirect so that no other unwanted code is executed.', + 'functions' => array( + 'wp_redirect', + ), + ), + + // @link https://vip.wordpress.com/documentation/vip/code-review-what-we-look-for/#mobile-detection + 'wp_is_mobile' => array( + 'type' => 'error', + 'message' => '%s When targeting mobile visitors, jetpack_is_mobile() should be used instead of wp_is_mobile. It is more robust and works better with full page caching.', + 'functions' => array( + 'wp_is_mobile', + ), + ), + + // @link https://vip.wordpress.com/documentation/vip/code-review-what-we-look-for/#encoding-values-used-when-creating-a-url-or-passed-to-add_query_arg + 'urlencode' => array( + 'type' => 'warning', + 'message' => '%s should only be used when dealing with legacy applications, rawurlencode() should now be used instead. See http://php.net/manual/en/function.rawurlencode.php and http://www.faqs.org/rfcs/rfc3986.html', + 'functions' => array( + 'urlencode', + ), + ), + + // @link https://vip.wordpress.com/documentation/vip/code-review-what-we-look-for/#settings-alteration + 'runtime_configuration' => array( + 'type' => 'error', + 'message' => '%s is prohibited, changing configuration at runtime is not allowed on VIP Production.', + 'functions' => array( + 'dl', + 'error_reporting', + 'ini_alter', + 'ini_restore', + 'ini_set', + 'magic_quotes_runtime', + 'set_magic_quotes_runtime', + 'apache_setenv', + 'putenv', + 'set_include_path', + 'restore_include_path', + ), + ), + + 'prevent_path_disclosure' => array( + 'type' => 'error', + 'message' => '%s is prohibited as it can lead to full path disclosure.', + 'functions' => array( + 'error_reporting', + 'phpinfo', + ), + ), + ); - } -}//end class + } // end getGroups() + +} // End class. diff --git a/WordPress/Sniffs/VIP/RestrictedVariablesSniff.php b/WordPress/Sniffs/VIP/RestrictedVariablesSniff.php index 22461222ab..51822b4d17 100644 --- a/WordPress/Sniffs/VIP/RestrictedVariablesSniff.php +++ b/WordPress/Sniffs/VIP/RestrictedVariablesSniff.php @@ -1,16 +1,25 @@ + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ -class WordPress_Sniffs_VIP_RestrictedVariablesSniff extends WordPress_Sniffs_Variables_VariableRestrictionsSniff -{ + +/** + * Restricts usage of some variables in VIP context. + * + * @link https://vip.wordpress.com/documentation/vip/code-review-what-we-look-for/ + * + * @package WPCS\WordPressCodingStandards + * + * @since 0.3.0 + */ +class WordPress_Sniffs_VIP_RestrictedVariablesSniff extends WordPress_AbstractVariableRestrictionsSniff { /** - * Groups of variables to restrict + * Groups of variables to restrict. * * Example: groups => array( * 'wpdb' => array( @@ -26,27 +35,29 @@ class WordPress_Sniffs_VIP_RestrictedVariablesSniff extends WordPress_Sniffs_Var */ public function getGroups() { return array( + // @link https://vip.wordpress.com/documentation/vip/code-review-what-we-look-for/#working-with-wp_users-and-user_meta 'user_meta' => array( - 'type' => 'error', - 'message' => 'Usage of users/usermeta tables is highly discouraged in VIP context, For storing user additional user metadata, you should look at User Attributes.', + 'type' => 'error', + 'message' => 'Usage of users/usermeta tables is highly discouraged in VIP context, For storing user additional user metadata, you should look at User Attributes.', 'object_vars' => array( '$wpdb->users', '$wpdb->usermeta', - ), ), + ), + + // @link https://vip.wordpress.com/documentation/vip/code-review-what-we-look-for/#caching-constraints 'cache_constraints' => array( - 'type' => 'warning', - 'message' => 'Due to using Batcache, server side based client related logic will not work, use JS instead.', - 'variables' => array( + 'type' => 'warning', + 'message' => 'Due to using Batcache, server side based client related logic will not work, use JS instead.', + 'variables' => array( '$_COOKIE', ), 'array_members' => array( '$_SERVER[\'HTTP_USER_AGENT\']', '$_SERVER[\'REMOTE_ADDR\']', - ), ), - ); + ), + ); } - -}//end class +} // End class. diff --git a/WordPress/Sniffs/VIP/SessionFunctionsUsageSniff.php b/WordPress/Sniffs/VIP/SessionFunctionsUsageSniff.php index aad293492d..b3d9510aaf 100644 --- a/WordPress/Sniffs/VIP/SessionFunctionsUsageSniff.php +++ b/WordPress/Sniffs/VIP/SessionFunctionsUsageSniff.php @@ -1,58 +1,78 @@ - * @see https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards/issues/75 + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ -class WordPress_Sniffs_VIP_SessionFunctionsUsageSniff extends Generic_Sniffs_PHP_ForbiddenFunctionsSniff -{ - /** - * A list of forbidden functions with their alternatives. - * - * The value is NULL if no alternative exists. IE, the - * function should just not be used. - * - * @var array(string => string|null) - */ - public $forbiddenFunctions = array( - 'session_cache_expire' => null, - 'session_cache_limiter' => null, - 'session_commit' => null, - 'session_decode' => null, - 'session_destroy' => null, - 'session_encode' => null, - 'session_get_cookie_params' => null, - 'session_id' => null, - 'session_is_registered' => null, - 'session_module_name' => null, - 'session_name' => null, - 'session_regenerate_id' => null, - 'session_register_shutdown' => null, - 'session_register' => null, - 'session_save_path' => null, - 'session_set_cookie_params' => null, - 'session_set_save_handler' => null, - 'session_start' => null, - 'session_status' => null, - 'session_unregister' => null, - 'session_unset' => null, - 'session_write_close' => null, - ); +if ( ! class_exists( 'Generic_Sniffs_PHP_ForbiddenFunctionsSniff', true ) ) { + throw new PHP_CodeSniffer_Exception( 'Class Generic_Sniffs_PHP_ForbiddenFunctionsSniff not found' ); +} - protected function addError( $phpcsFile, $stackPtr, $function, $pattern = null ) - { - $data = array($function); - $error = 'The use of PHP session function %s() is prohibited.'; +/** + * Discourages the use of session functions. + * + * @link https://vip.wordpress.com/documentation/vip/code-review-what-we-look-for/#session_start-and-other-session-related-functions + * + * @package WPCS\WordPressCodingStandards + * + * @since 0.3.0 + */ +class WordPress_Sniffs_VIP_SessionFunctionsUsageSniff extends Generic_Sniffs_PHP_ForbiddenFunctionsSniff { - $phpcsFile->addError( $error, $stackPtr, $function, $data ); + /** + * A list of forbidden functions with their alternatives. + * + * The value is NULL if no alternative exists. I.e. the + * function should just not be used. + * + * @var array(string => string|null) + */ + public $forbiddenFunctions = array( + 'session_cache_expire' => null, + 'session_cache_limiter' => null, + 'session_commit' => null, + 'session_decode' => null, + 'session_destroy' => null, + 'session_encode' => null, + 'session_get_cookie_params' => null, + 'session_id' => null, + 'session_is_registered' => null, + 'session_module_name' => null, + 'session_name' => null, + 'session_regenerate_id' => null, + 'session_register_shutdown' => null, + 'session_register' => null, + 'session_save_path' => null, + 'session_set_cookie_params' => null, + 'session_set_save_handler' => null, + 'session_start' => null, + 'session_status' => null, + 'session_unregister' => null, + 'session_unset' => null, + 'session_write_close' => null, + ); - }//end addError() + /** + * Generates the error or warning for this sniff. + * + * Overloads parent addError method. + * + * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the forbidden function + * in the token array. + * @param string $function The name of the forbidden function. + * @param string $pattern The pattern used for the match. + * + * @return void + */ + protected function addError( $phpcsFile, $stackPtr, $function, $pattern = null ) { + $data = array( $function ); + $error = 'The use of PHP session function %s() is prohibited.'; -}//end class + $phpcsFile->addError( $error, $stackPtr, $function, $data ); + } +} // End class. diff --git a/WordPress/Sniffs/VIP/SessionVariableUsageSniff.php b/WordPress/Sniffs/VIP/SessionVariableUsageSniff.php index 37255fb309..1db40d9d69 100644 --- a/WordPress/Sniffs/VIP/SessionVariableUsageSniff.php +++ b/WordPress/Sniffs/VIP/SessionVariableUsageSniff.php @@ -1,54 +1,56 @@ - * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards/issues/75 + * @link https://vip.wordpress.com/documentation/vip/code-review-what-we-look-for/#session_start-and-other-session-related-functions + * + * @package WPCS\WordPressCodingStandards + * + * @since 0.3.0 + * @since 0.10.0 The sniff no longer needlessly extends the Generic_Sniffs_PHP_ForbiddenFunctionsSniff + * which it didn't use. */ -class WordPress_Sniffs_VIP_SessionVariableUsageSniff extends Generic_Sniffs_PHP_ForbiddenFunctionsSniff -{ +class WordPress_Sniffs_VIP_SessionVariableUsageSniff implements PHP_CodeSniffer_Sniff { /** - * Returns an array of tokens this test wants to listen for. - * - * @return array - */ - public function register() - { - return array( - T_VARIABLE, - ); - - }//end register() - + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + return array( + T_VARIABLE, + ); - /** - * Processes this test, when one of its tokens is encountered. - * - * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. - * @param int $stackPtr The position of the current token - * in the stack passed in $tokens. - * - * @todo Allow T_CONSTANT_ENCAPSED_STRING? - * - * @return void - */ - public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) - { - $tokens = $phpcsFile->getTokens(); + } - if ( $tokens[$stackPtr]['content'] == '$_SESSION' ) { - $phpcsFile->addError( 'Usage of $_SESSION variable is prohibited.', $stackPtr, 'SessionVarsProhibited' ); - } - - - }//end process() - - - -}//end class + /** + * Processes this test, when one of its tokens is encountered. + * + * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @todo Allow T_CONSTANT_ENCAPSED_STRING? + * + * @return void + */ + public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) { + $tokens = $phpcsFile->getTokens(); + + if ( '$_SESSION' === $tokens[ $stackPtr ]['content'] ) { + $phpcsFile->addError( 'Usage of $_SESSION variable is prohibited.', $stackPtr, 'SessionVarsProhibited' ); + } + + } + +} // End class. diff --git a/WordPress/Sniffs/VIP/SlowDBQuerySniff.php b/WordPress/Sniffs/VIP/SlowDBQuerySniff.php index 3912301748..843b2891a2 100644 --- a/WordPress/Sniffs/VIP/SlowDBQuerySniff.php +++ b/WordPress/Sniffs/VIP/SlowDBQuerySniff.php @@ -1,24 +1,33 @@ + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ -class WordPress_Sniffs_VIP_SlowDBQuerySniff extends WordPress_Sniffs_Arrays_ArrayAssignmentRestrictionsSniff -{ + +/** + * Flag potentially slow queries. + * + * @link https://vip.wordpress.com/documentation/vip/code-review-what-we-look-for/#uncached-pageload + * + * @package WPCS\WordPressCodingStandards + * + * @since 0.3.0 + */ +class WordPress_Sniffs_VIP_SlowDBQuerySniff extends WordPress_AbstractArrayAssignmentRestrictionsSniff { /** - * Groups of variables to restrict + * Groups of variables to restrict. * This should be overridden in extending classes. * * Example: groups => array( * 'wpdb' => array( - * 'type' => 'error' | 'warning', - * 'message' => 'Dont use this one please!', - * 'variables' => array( '$val', '$var' ), - * 'object_vars' => array( '$foo->bar', .. ), + * 'type' => 'error' | 'warning', + * 'message' => 'Dont use this one please!', + * 'variables' => array( '$val', '$var' ), + * 'object_vars' => array( '$foo->bar', .. ), * 'array_members' => array( '$foo['bar']', .. ), * ) * ) @@ -28,15 +37,53 @@ class WordPress_Sniffs_VIP_SlowDBQuerySniff extends WordPress_Sniffs_Arrays_Arra public function getGroups() { return array( 'slow_db_query' => array( - 'type' => 'warning', + 'type' => 'warning', 'message' => 'Detected usage of %s, possible slow query.', - 'keys' => array( + 'keys' => array( 'tax_query', 'meta_query', 'meta_key', 'meta_value', - ), - ) - ); + ), + ), + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @since 0.10.0 + * + * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) { + + $this->init( $phpcsFile ); + + if ( $this->has_whitelist_comment( 'tax_query', $stackPtr ) ) { + return; + } + + parent::process( $phpcsFile, $stackPtr ); } -}//end class + + /** + * Callback to process each confirmed key, to check value. + * This must be extended to add the logic to check assignment value. + * + * @param string $key Array index / key. + * @param mixed $val Assigned value. + * @param int $line Token line. + * @param array $group Group definition. + * @return mixed FALSE if no match, TRUE if matches, STRING if matches + * with custom error message passed to ->process(). + */ + public function callback( $key, $val, $line, $group ) { + return true; + } + +} // End class. diff --git a/WordPress/Sniffs/VIP/SuperGlobalInputUsageSniff.php b/WordPress/Sniffs/VIP/SuperGlobalInputUsageSniff.php index 4d4f9c7ee5..b0c75fb045 100644 --- a/WordPress/Sniffs/VIP/SuperGlobalInputUsageSniff.php +++ b/WordPress/Sniffs/VIP/SuperGlobalInputUsageSniff.php @@ -1,28 +1,35 @@ - * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards/issues/79 + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ -class WordPress_Sniffs_VIP_SuperGlobalInputUsageSniff extends WordPress_Sniff -{ + +/** + * Flag any usage of super global input var ( _GET / _POST / etc. ). + * + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards/issues/79 + * + * @package WPCS\WordPressCodingStandards + * + * @since 0.3.0 + * @since 0.4.0 This class now extends WordPress_Sniff. + */ +class WordPress_Sniffs_VIP_SuperGlobalInputUsageSniff extends WordPress_Sniff { /** * Returns an array of tokens this test wants to listen for. * * @return array */ - public function register() - { + public function register() { return array( - T_VARIABLE, - ); - - }//end register() + T_VARIABLE, + ); + } /** * Processes this test, when one of its tokens is encountered. @@ -33,27 +40,26 @@ public function register() * * @return void */ - public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) - { + public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) { $this->init( $phpcsFile ); - $tokens = $phpcsFile->getTokens(); - // Check for global input variable - if ( ! in_array( $tokens[ $stackPtr ]['content'], WordPress_Sniff::$input_superglobals ) ) { + // Check for global input variable. + if ( ! in_array( $this->tokens[ $stackPtr ]['content'], self::$input_superglobals, true ) ) { return; } - $varName = $tokens[$stackPtr]['content']; + $varName = $this->tokens[ $stackPtr ]['content']; - // If we're overriding a superglobal with an assignment, no need to test + // If we're overriding a superglobal with an assignment, no need to test. if ( $this->is_assignment( $stackPtr ) ) { return; } - // Check for whitelisting comment + // Check for whitelisting comment. if ( ! $this->has_whitelist_comment( 'input var', $stackPtr ) ) { - $phpcsFile->addWarning( 'Detected access of super global var %s, probably need manual inspection.', $stackPtr, 'AccessDetected', array( $varName ) ); + $phpcsFile->addWarning( 'Detected access of super global var %s, probably needs manual inspection.', $stackPtr, 'AccessDetected', array( $varName ) ); } - }//end process() -}//end class + } + +} // End class. diff --git a/WordPress/Sniffs/VIP/TimezoneChangeSniff.php b/WordPress/Sniffs/VIP/TimezoneChangeSniff.php index 36d8daad08..76e486a0e3 100644 --- a/WordPress/Sniffs/VIP/TimezoneChangeSniff.php +++ b/WordPress/Sniffs/VIP/TimezoneChangeSniff.php @@ -1,35 +1,56 @@ - * @see http://vip.wordpress.com/documentation/use-current_time-not-date_default_timezone_set/ + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ -class WordPress_Sniffs_VIP_TimezoneChangeSniff extends Generic_Sniffs_PHP_ForbiddenFunctionsSniff -{ - /** - * A list of forbidden functions with their alternatives. - * - * The value is NULL if no alternative exists. IE, the - * function should just not be used. - * - * @var array(string => string|null) - */ - public $forbiddenFunctions = array( - 'date_default_timezone_set' => null, - ); +if ( ! class_exists( 'Generic_Sniffs_PHP_ForbiddenFunctionsSniff', true ) ) { + throw new PHP_CodeSniffer_Exception( 'Class Generic_Sniffs_PHP_ForbiddenFunctionsSniff not found' ); +} + +/** + * Disallow the changing of timezone. + * + * @link http://vip.wordpress.com/documentation/use-current_time-not-date_default_timezone_set/ + * + * @package WPCS\WordPressCodingStandards + * + * @since 0.3.0 + */ +class WordPress_Sniffs_VIP_TimezoneChangeSniff extends Generic_Sniffs_PHP_ForbiddenFunctionsSniff { - protected function addError( $phpcsFile, $stackPtr, $function, $pattern = null ) - { - $error = 'Using date_default_timezone_set() and similar isn’t allowed, instead use WP internal timezone support.'; - $phpcsFile->addError( $error, $stackPtr, $function ); + /** + * A list of forbidden functions with their alternatives. + * + * The value is NULL if no alternative exists. IE, the + * function should just not be used. + * + * @var array(string => string|null) + */ + public $forbiddenFunctions = array( + 'date_default_timezone_set' => null, + ); - }//end addError() + /** + * Generates the error or warning for this sniff. + * + * Overloads parent addError method. + * + * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the forbidden function + * in the token array. + * @param string $function The name of the forbidden function. + * @param string $pattern The pattern used for the match. + * + * @return void + */ + protected function addError( $phpcsFile, $stackPtr, $function, $pattern = null ) { + $error = 'Using date_default_timezone_set() and similar isn\'t allowed, instead use WP internal timezone support.'; + $phpcsFile->addError( $error, $stackPtr, $function ); -}//end class + } +} // End class. diff --git a/WordPress/Sniffs/VIP/ValidatedSanitizedInputSniff.php b/WordPress/Sniffs/VIP/ValidatedSanitizedInputSniff.php index 791321e662..f6c0853475 100644 --- a/WordPress/Sniffs/VIP/ValidatedSanitizedInputSniff.php +++ b/WordPress/Sniffs/VIP/ValidatedSanitizedInputSniff.php @@ -1,19 +1,28 @@ - * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards/issues/69 + * @since 0.3.0 + * @since 0.4.0 This class now extends WordPress_Sniff. + * @since 0.5.0 Method getArrayIndexKey() has been moved to WordPress_Sniff. */ class WordPress_Sniffs_VIP_ValidatedSanitizedInputSniff extends WordPress_Sniff { /** - * Check for validation functions for a variable within its own parenthesis only + * Check for validation functions for a variable within its own parenthesis only. + * * @var boolean */ public $check_validation_in_scope_only = false; @@ -71,13 +80,13 @@ public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) { // Merge any custom functions with the defaults, if we haven't already. if ( ! self::$addedCustomFunctions ) { - WordPress_Sniff::$sanitizingFunctions = array_merge( - WordPress_Sniff::$sanitizingFunctions, + self::$sanitizingFunctions = array_merge( + self::$sanitizingFunctions, array_flip( $this->customSanitizingFunctions ) ); - WordPress_Sniff::$unslashingSanitizingFunctions = array_merge( - WordPress_Sniff::$unslashingSanitizingFunctions, + self::$unslashingSanitizingFunctions = array_merge( + self::$unslashingSanitizingFunctions, array_flip( $this->customUnslashingSanitizingFunctions ) ); @@ -85,28 +94,27 @@ public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) { } $this->init( $phpcsFile ); - $tokens = $phpcsFile->getTokens(); - $superglobals = WordPress_Sniff::$input_superglobals; + $superglobals = self::$input_superglobals; - // Handling string interpolation - if ( T_DOUBLE_QUOTED_STRING === $tokens[ $stackPtr ]['code'] ) { + // Handling string interpolation. + if ( T_DOUBLE_QUOTED_STRING === $this->tokens[ $stackPtr ]['code'] ) { $interpolated_variables = array_map( create_function( '$symbol', 'return "$" . $symbol;' ), // Replace with closure when 5.3 is minimum requirement for PHPCS. - $this->get_interpolated_variables( $tokens[ $stackPtr ]['content'] ) + $this->get_interpolated_variables( $this->tokens[ $stackPtr ]['content'] ) ); foreach ( array_intersect( $interpolated_variables, $superglobals ) as $bad_variable ) { - $phpcsFile->addError( 'Detected usage of a non-sanitized, non-validated input variable %s: %s', $stackPtr, null, array( $bad_variable, $tokens[ $stackPtr ]['content'] ) ); + $phpcsFile->addError( 'Detected usage of a non-sanitized, non-validated input variable %s: %s', $stackPtr, 'InputNotValidatedNotSanitized', array( $bad_variable, $this->tokens[ $stackPtr ]['content'] ) ); } return; } // Check if this is a superglobal. - if ( ! in_array( $tokens[ $stackPtr ]['content'], $superglobals ) ) { + if ( ! in_array( $this->tokens[ $stackPtr ]['content'], $superglobals, true ) ) { return; } - // If we're overriding a superglobal with an assignment, no need to test + // If we're overriding a superglobal with an assignment, no need to test. if ( $this->is_assignment( $stackPtr ) ) { return; } @@ -122,9 +130,11 @@ public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) { return; } + $error_data = array( $this->tokens[ $stackPtr ]['content'] ); + // Check for validation first. if ( ! $this->is_validated( $stackPtr, $array_key, $this->check_validation_in_scope_only ) ) { - $phpcsFile->addError( 'Detected usage of a non-validated input variable: %s', $stackPtr, 'InputNotValidated', array( $tokens[ $stackPtr ]['content'] ) ); + $phpcsFile->addError( 'Detected usage of a non-validated input variable: %s', $stackPtr, 'InputNotValidated', $error_data ); // return; // Should we just return and not look for sanitizing functions ? } @@ -137,13 +147,11 @@ public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) { return; } - // Now look for sanitizing functions + // Now look for sanitizing functions. if ( ! $this->is_sanitized( $stackPtr, true ) ) { - $phpcsFile->addError( 'Detected usage of a non-sanitized input variable: %s', $stackPtr, 'InputNotSanitized', array( $tokens[ $stackPtr ]['content'] ) ); + $phpcsFile->addError( 'Detected usage of a non-sanitized input variable: %s', $stackPtr, 'InputNotSanitized', $error_data ); } - return; - } // end process() -} // end class +} // End class. diff --git a/WordPress/Sniffs/Variables/GlobalVariablesSniff.php b/WordPress/Sniffs/Variables/GlobalVariablesSniff.php index 69bf0ac024..c243b7e0d8 100644 --- a/WordPress/Sniffs/Variables/GlobalVariablesSniff.php +++ b/WordPress/Sniffs/Variables/GlobalVariablesSniff.php @@ -1,16 +1,29 @@ + * @package WPCS\WordPressCodingStandards + * + * @since 0.3.0 + * @since 0.4.0 This class now extends WordPress_Sniff. */ -class WordPress_Sniffs_Variables_GlobalVariablesSniff extends WordPress_Sniff -{ +class WordPress_Sniffs_Variables_GlobalVariablesSniff extends WordPress_Sniff { + /** + * List of global WP variables. + * + * @var array + */ public $globals = array( 'comment', 'comment_alt', @@ -275,28 +288,27 @@ public function register() { */ public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) { $this->init( $phpcsFile ); - $tokens = $phpcsFile->getTokens(); - $token = $tokens[ $stackPtr ]; + $token = $this->tokens[ $stackPtr ]; - $search = array(); // Array of globals to watch for + $search = array(); // Array of globals to watch for. if ( T_VARIABLE === $token['code'] && '$GLOBALS' === $token['content'] ) { - $bracketPtr = $phpcsFile->findNext( array( T_WHITESPACE ), $stackPtr + 1, null, true ); + $bracketPtr = $phpcsFile->findNext( array( T_WHITESPACE ), ( $stackPtr + 1 ), null, true ); - if ( T_OPEN_SQUARE_BRACKET !== $tokens[ $bracketPtr ]['code'] ) { + if ( T_OPEN_SQUARE_BRACKET !== $this->tokens[ $bracketPtr ]['code'] ) { return; } - $varPtr = $phpcsFile->findNext( T_WHITESPACE, $bracketPtr + 1, $tokens[ $bracketPtr ]['bracket_closer'], true ); - $varToken = $tokens[ $varPtr ]; + $varPtr = $phpcsFile->findNext( T_WHITESPACE, ( $bracketPtr + 1 ), $this->tokens[ $bracketPtr ]['bracket_closer'], true ); + $varToken = $this->tokens[ $varPtr ]; - if ( ! in_array( trim( $varToken['content'], '\'"' ), $this->globals ) ) { + if ( ! in_array( trim( $varToken['content'], '\'"' ), $this->globals, true ) ) { return; } - $assignment = $phpcsFile->findNext( T_WHITESPACE, $tokens[ $bracketPtr ]['bracket_closer'] + 1, null, true ); + $assignment = $phpcsFile->findNext( T_WHITESPACE, ( $this->tokens[ $bracketPtr ]['bracket_closer'] + 1 ), null, true ); - if ( $assignment && T_EQUAL === $tokens[ $assignment ]['code'] ) { + if ( $assignment && T_EQUAL === $this->tokens[ $assignment ]['code'] ) { if ( ! $this->has_whitelist_comment( 'override', $assignment ) ) { $phpcsFile->addError( 'Overriding WordPress globals is prohibited', $stackPtr, 'OverrideProhibited' ); return; @@ -304,19 +316,19 @@ public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) { } return; - } - elseif ( T_GLOBAL === $token['code'] ) { - $ptr = $stackPtr + 1; + + } elseif ( T_GLOBAL === $token['code'] ) { + $ptr = ( $stackPtr + 1 ); while ( $ptr ) { $ptr++; - $var = $tokens[ $ptr ]; + $var = $this->tokens[ $ptr ]; if ( T_VARIABLE === $var['code'] ) { $varname = substr( $var['content'], 1 ); - if ( in_array( $varname, $this->globals ) ) { + if ( in_array( $varname, $this->globals, true ) ) { $search[] = $varname; } } - // Halt the loop + // Halt the loop. if ( T_SEMICOLON === $var['code'] ) { $ptr = false; } @@ -325,11 +337,11 @@ public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) { return; } - // Check for assignments to collected global vars - foreach ( $tokens as $ptr => $token ) { - if ( T_VARIABLE === $token['code'] && in_array( substr( $token['content'], 1 ), $search ) ) { - $next = $phpcsFile->findNext( array( T_WHITESPACE, T_COMMENT ), $ptr + 1, null, true, null, true ); - if ( T_EQUAL === $tokens[ $next ]['code'] ) { + // Check for assignments to collected global vars. + foreach ( $this->tokens as $ptr => $token ) { + if ( T_VARIABLE === $token['code'] && in_array( substr( $token['content'], 1 ), $search, true ) ) { + $next = $phpcsFile->findNext( PHP_CodeSniffer_Tokens::$emptyTokens, ( $ptr + 1 ), null, true, null, true ); + if ( T_EQUAL === $this->tokens[ $next ]['code'] ) { if ( ! $this->has_whitelist_comment( 'override', $next ) ) { $phpcsFile->addError( 'Overriding WordPress globals is prohibited', $ptr, 'OverrideProhibited' ); } @@ -337,5 +349,6 @@ public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) { } } } - } -} + } // end process() + +} // End class. diff --git a/WordPress/Sniffs/Variables/VariableRestrictionsSniff.php b/WordPress/Sniffs/Variables/VariableRestrictionsSniff.php index 7410115fb0..7e6b96262b 100644 --- a/WordPress/Sniffs/Variables/VariableRestrictionsSniff.php +++ b/WordPress/Sniffs/Variables/VariableRestrictionsSniff.php @@ -1,53 +1,30 @@ + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ -class WordPress_Sniffs_Variables_VariableRestrictionsSniff implements PHP_CodeSniffer_Sniff -{ - /** - * Exclude groups - * - * Example: 'foo,bar' - * - * @var string Comma-delimited group list - */ - public $exclude = ''; - - /** - * Groups of variable data to check against. - * Don't use this in extended classes, override getGroups() instead. - * This is only used for Unit tests. - * - * @var array - */ - public static $groups = array(); - - - /** - * Returns an array of tokens this test wants to listen for. - * - * @return array - */ - public function register() - { - return array( - T_VARIABLE, - T_OBJECT_OPERATOR, - T_DOUBLE_COLON, - T_OPEN_SQUARE_BRACKET, - T_DOUBLE_QUOTED_STRING, - ); - - }//end register() +/** + * Restricts usage of some variables. + * + * @package WPCS\WordPressCodingStandards + * + * @since 0.3.0 + * @deprecated 0.10.0 The functionality which used to be contained in this class has been moved to + * the WordPress_AbstractVariableRestrictionsSniff class. + * This class is left here to prevent backward-compatibility breaks for + * custom sniffs extending the old class and references to this + * sniff from custom phpcs.xml files. + * This file is also still used to unit test the abstract class. + * @see WordPress_AbstractVariableRestrictionsSniff + */ +class WordPress_Sniffs_Variables_VariableRestrictionsSniff extends WordPress_AbstractVariableRestrictionsSniff { /** - * Groups of variables to restrict - * This should be overridden in extending classes. + * Groups of variables to restrict. * * Example: groups => array( * 'wpdb' => array( @@ -62,122 +39,7 @@ public function register() * @return array */ public function getGroups() { - return self::$groups; - } - - - /** - * Processes this test, when one of its tokens is encountered. - * - * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. - * @param int $stackPtr The position of the current token - * in the stack passed in $tokens. - * - * @return void - */ - public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) - { - $tokens = $phpcsFile->getTokens(); - - $token = $tokens[$stackPtr]; - - $exclude = explode( ',', $this->exclude ); - - $groups = $this->getGroups(); - - if ( empty( $groups ) ) { - return count( $tokens ) + 1; - } - - // Check if it is a function not a variable - if ( in_array( $token['code'], array( T_OBJECT_OPERATOR, T_DOUBLE_COLON ) ) ) { // This only works for object vars and array members - $method = $phpcsFile->findNext( T_WHITESPACE, $stackPtr + 1, null, true ); - $possible_parenthesis = $phpcsFile->findNext( T_WHITESPACE, $method + 1, null, true ); - if ( $tokens[$possible_parenthesis]['code'] == T_OPEN_PARENTHESIS ) { - return; // So .. it is a function after all ! - } - } - - foreach ( $groups as $groupName => $group ) { - - if ( in_array( $groupName, $exclude ) ) { - continue; - } - - $patterns = array(); - - // Simple variable - if ( in_array( $token['code'], array( T_VARIABLE, T_DOUBLE_QUOTED_STRING ) ) && ! empty( $group['variables'] ) ) { - $patterns = array_merge( $patterns, $group['variables'] ); - $var = $token['content']; - } - // Object var, ex: $foo->bar / $foo::bar / Foo::bar / Foo::$bar - elseif ( in_array( $token['code'], array( T_OBJECT_OPERATOR, T_DOUBLE_COLON, T_DOUBLE_QUOTED_STRING ) ) && ! empty( $group['object_vars'] ) ) { - $patterns = array_merge( $patterns, $group['object_vars'] ); - - $owner = $phpcsFile->findPrevious( array( T_VARIABLE, T_STRING ), $stackPtr ); - $child = $phpcsFile->findNext( array( T_STRING, T_VAR, T_VARIABLE ), $stackPtr ); - $var = implode( '', array( $tokens[$owner]['content'], $token['content'], $tokens[$child]['content'] ) ); - } - // Array members - elseif ( in_array( $token['code'], array( T_OPEN_SQUARE_BRACKET, T_DOUBLE_QUOTED_STRING ) ) && ! empty( $group['array_members'] ) ) { - $patterns = array_merge( $patterns, $group['array_members'] ); - - $owner = $phpcsFile->findPrevious( array( T_VARIABLE ), $stackPtr ); - $inside = $phpcsFile->getTokensAsString( $stackPtr, $token['bracket_closer'] - $stackPtr + 1 ); - $var = implode( '', array( $tokens[$owner]['content'], $inside ) ); - } - else { - continue; - } - - if ( empty( $patterns ) ) { - continue; - } - - $patterns = array_map( array( $this, 'test_patterns' ), $patterns ); - - $pattern = implode( '|', $patterns ); - - $delim = ( $token['code'] != T_OPEN_SQUARE_BRACKET ) ? '\b' : ''; - - if ( $token['code'] == T_DOUBLE_QUOTED_STRING ) { - $var = $token['content']; - } - - if ( preg_match( '#(' . $pattern . ')' . $delim .'#', $var, $match ) < 1 ) { - continue; - } - - if ( $group['type'] == 'warning' ) { - $addWhat = array( $phpcsFile, 'addWarning' ); - } else { - $addWhat = array( $phpcsFile, 'addError' ); - } - - call_user_func( - $addWhat, - $group['message'], - $stackPtr, - $groupName, - array( $var ) - ); - - return; // Show one error only - - } - - }//end process() - - private function test_patterns( $pattern ) { - $pattern = preg_quote( $pattern, '#' ); - $pattern = preg_replace( - array( '#\\\\\*#', '[\'"]' ), - array( '.*', '\'' ), - $pattern - ); - return $pattern; + return parent::$groups; } - -}//end class +} // End class. diff --git a/WordPress/Sniffs/WP/EnqueuedResourcesSniff.php b/WordPress/Sniffs/WP/EnqueuedResourcesSniff.php index 0f03f844a5..65d5db07fb 100644 --- a/WordPress/Sniffs/WP/EnqueuedResourcesSniff.php +++ b/WordPress/Sniffs/WP/EnqueuedResourcesSniff.php @@ -1,55 +1,58 @@ + * @since 0.3.0 */ -class WordPress_Sniffs_WP_EnqueuedResourcesSniff implements PHP_CodeSniffer_Sniff -{ - - /** - * Returns an array of tokens this test wants to listen for. - * - * @return array - */ - public function register() - { - return array( - T_CONSTANT_ENCAPSED_STRING, - T_DOUBLE_QUOTED_STRING, - T_INLINE_HTML, - ); - - }//end register() - - - /** - * Processes this test, when one of its tokens is encountered. - * - * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. - * @param int $stackPtr The position of the current token - * in the stack passed in $tokens. - * - * @return void - */ - public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) - { - $tokens = $phpcsFile->getTokens(); - $token = $tokens[$stackPtr]; - - if ( preg_match( '#rel=[\'"]?stylesheet[\'"]?#', $token['content'], $matches ) > 0 ) { - $phpcsFile->addError( 'Stylesheets must be registered/enqueued via wp_enqueue_style', $stackPtr, 'NonEnqueuedStylesheet' ); - } - - if ( preg_match( '#]*(?<=src=)#', $token['content'], $matches ) > 0 ) { - $phpcsFile->addError( 'Scripts must be registered/enqueued via wp_enqueue_script', $stackPtr, 'NonEnqueuedScript' ); - } - - }//end process() - - -}//end class +class WordPress_Sniffs_WP_EnqueuedResourcesSniff implements PHP_CodeSniffer_Sniff { + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + return array( + T_CONSTANT_ENCAPSED_STRING, + T_DOUBLE_QUOTED_STRING, + T_INLINE_HTML, + ); + + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) { + $tokens = $phpcsFile->getTokens(); + $token = $tokens[ $stackPtr ]; + + if ( preg_match( '#rel=[\'"]?stylesheet[\'"]?#', $token['content'] ) > 0 ) { + $phpcsFile->addError( 'Stylesheets must be registered/enqueued via wp_enqueue_style', $stackPtr, 'NonEnqueuedStylesheet' ); + } + + if ( preg_match( '#]*(?<=src=)#', $token['content'] ) > 0 ) { + $phpcsFile->addError( 'Scripts must be registered/enqueued via wp_enqueue_script', $stackPtr, 'NonEnqueuedScript' ); + } + + } // end process() + +} // End class. diff --git a/WordPress/Sniffs/WP/I18nSniff.php b/WordPress/Sniffs/WP/I18nSniff.php new file mode 100644 index 0000000000..815edb95cd --- /dev/null +++ b/WordPress/Sniffs/WP/I18nSniff.php @@ -0,0 +1,376 @@ +getFilename() + * @link https://youtrack.jetbrains.com/issue/WI-17740 + * + * @var string + */ + public $text_domain; + + /** + * Allow unit tests to override the supplied text_domain. + * + * @todo While it doesn't work, ideally this should be able to be done in \WordPress_Tests_WP_I18nUnitTest::setUp() + * + * @var string + */ + static $text_domain_override; + + /** + * The I18N functions in use in WP. + * + * @var array => + */ + public $i18n_functions = array( + 'translate' => 'simple', + '__' => 'simple', + 'esc_attr__' => 'simple', + 'esc_html__' => 'simple', + '_e' => 'simple', + 'esc_attr_e' => 'simple', + 'esc_html_e' => 'simple', + 'translate_with_gettext_context' => 'context', + '_x' => 'context', + '_ex' => 'context', + 'esc_attr_x' => 'context', + 'esc_html_x' => 'context', + '_n' => 'number', + '_nx' => 'number_context', + '_n_noop' => 'noopnumber', + '_nx_noop' => 'noopnumber_context', + ); + + /** + * These Regexes copied from http://php.net/manual/en/function.sprintf.php#93552 + * + * @var string + */ + public static $sprintf_placeholder_regex = '/(?:%%|(%(?:[0-9]+\$)?[+-]?(?:[ 0]|\'.)?-?[0-9]*(?:\.[0-9]+)?[bcdeufFos]))/'; + + /** + * "Unordered" means there's no position specifier: '%s', not '%2$s'. + * + * @var string + */ + public static $unordered_sprintf_placeholder_regex = '/(?:%%|(?:%[+-]?(?:[ 0]|\'.)?-?[0-9]*(?:\.[0-9]+)?[bcdeufFosxX]))/'; + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + return array( + T_STRING, + ); + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param PHP_CodeSniffer_File $phpcs_file The file being scanned. + * @param int $stack_ptr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process( PHP_CodeSniffer_File $phpcs_file, $stack_ptr ) { + $tokens = $phpcs_file->getTokens(); + $token = $tokens[ $stack_ptr ]; + + if ( ! empty( self::$text_domain_override ) ) { + $this->text_domain = self::$text_domain_override; + } + + if ( '_' === $token['content'] ) { + $phpcs_file->addError( 'Found single-underscore "_()" function when double-underscore expected.', $stack_ptr, 'SingleUnderscoreGetTextFunction' ); + } + + if ( ! isset( $this->i18n_functions[ $token['content'] ] ) ) { + return; + } + $translation_function = $token['content']; + + if ( in_array( $translation_function, array( 'translate', 'translate_with_gettext_context' ), true ) ) { + $phpcs_file->addWarning( 'Use of the "%s()" function is reserved for low-level API usage.', $stack_ptr, 'LowLevelTranslationFunction', array( $translation_function ) ); + } + + $func_open_paren_token = $phpcs_file->findNext( T_WHITESPACE, ( $stack_ptr + 1 ), null, true ); + if ( ! $func_open_paren_token || T_OPEN_PARENTHESIS !== $tokens[ $func_open_paren_token ]['code'] ) { + return; + } + + $arguments_tokens = array(); + $argument_tokens = array(); + + // Look at arguments. + for ( $i = ( $func_open_paren_token + 1 ); $i < $tokens[ $func_open_paren_token ]['parenthesis_closer']; $i += 1 ) { + $this_token = $tokens[ $i ]; + $this_token['token_index'] = $i; + if ( in_array( $this_token['code'], PHP_CodeSniffer_Tokens::$emptyTokens, true ) ) { + continue; + } + if ( T_COMMA === $this_token['code'] ) { + $arguments_tokens[] = $argument_tokens; + $argument_tokens = array(); + continue; + } + + // Merge consecutive single or double quoted strings (when they span multiple lines). + if ( T_CONSTANT_ENCAPSED_STRING === $this_token['code'] || T_DOUBLE_QUOTED_STRING === $this_token['code'] ) { + for ( $j = ( $i + 1 ); $j < $tokens[ $func_open_paren_token ]['parenthesis_closer']; $j += 1 ) { + if ( $this_token['code'] === $tokens[ $j ]['code'] ) { + $this_token['content'] .= $tokens[ $j ]['content']; + $i = $j; + } else { + break; + } + } + } + $argument_tokens[] = $this_token; + + // Include everything up to and including the parenthesis_closer if this token has one. + if ( ! empty( $this_token['parenthesis_closer'] ) ) { + for ( $j = ( $i + 1 ); $j <= $this_token['parenthesis_closer']; $j += 1 ) { + $tokens[ $j ]['token_index'] = $j; + $argument_tokens[] = $tokens[ $j ]; + } + $i = $this_token['parenthesis_closer']; + } + } + if ( ! empty( $argument_tokens ) ) { + $arguments_tokens[] = $argument_tokens; + } + unset( $argument_tokens ); + + $argument_assertions = array(); + if ( 'simple' === $this->i18n_functions[ $translation_function ] ) { + $argument_assertions[] = array( 'arg_name' => 'text', 'tokens' => array_shift( $arguments_tokens ) ); + $argument_assertions[] = array( 'arg_name' => 'domain', 'tokens' => array_shift( $arguments_tokens ) ); + } elseif ( 'context' === $this->i18n_functions[ $translation_function ] ) { + $argument_assertions[] = array( 'arg_name' => 'text', 'tokens' => array_shift( $arguments_tokens ) ); + $argument_assertions[] = array( 'arg_name' => 'context', 'tokens' => array_shift( $arguments_tokens ) ); + $argument_assertions[] = array( 'arg_name' => 'domain', 'tokens' => array_shift( $arguments_tokens ) ); + } elseif ( 'number' === $this->i18n_functions[ $translation_function ] ) { + $argument_assertions[] = array( 'arg_name' => 'single', 'tokens' => array_shift( $arguments_tokens ) ); + $argument_assertions[] = array( 'arg_name' => 'plural', 'tokens' => array_shift( $arguments_tokens ) ); + array_shift( $arguments_tokens ); + $argument_assertions[] = array( 'arg_name' => 'domain', 'tokens' => array_shift( $arguments_tokens ) ); + } elseif ( 'number_context' === $this->i18n_functions[ $translation_function ] ) { + $argument_assertions[] = array( 'arg_name' => 'single', 'tokens' => array_shift( $arguments_tokens ) ); + $argument_assertions[] = array( 'arg_name' => 'plural', 'tokens' => array_shift( $arguments_tokens ) ); + array_shift( $arguments_tokens ); + $argument_assertions[] = array( 'arg_name' => 'context', 'tokens' => array_shift( $arguments_tokens ) ); + $argument_assertions[] = array( 'arg_name' => 'domain', 'tokens' => array_shift( $arguments_tokens ) ); + } elseif ( 'noopnumber' === $this->i18n_functions[ $translation_function ] ) { + $argument_assertions[] = array( 'arg_name' => 'single', 'tokens' => array_shift( $arguments_tokens ) ); + $argument_assertions[] = array( 'arg_name' => 'plural', 'tokens' => array_shift( $arguments_tokens ) ); + $argument_assertions[] = array( 'arg_name' => 'domain', 'tokens' => array_shift( $arguments_tokens ) ); + } elseif ( 'noopnumber_context' === $this->i18n_functions[ $translation_function ] ) { + $argument_assertions[] = array( 'arg_name' => 'single', 'tokens' => array_shift( $arguments_tokens ) ); + $argument_assertions[] = array( 'arg_name' => 'plural', 'tokens' => array_shift( $arguments_tokens ) ); + $argument_assertions[] = array( 'arg_name' => 'context', 'tokens' => array_shift( $arguments_tokens ) ); + $argument_assertions[] = array( 'arg_name' => 'domain', 'tokens' => array_shift( $arguments_tokens ) ); + } + + if ( ! empty( $arguments_tokens ) ) { + $phpcs_file->addError( 'Too many arguments for function "%s".', $func_open_paren_token, 'TooManyFunctionArgs', array( $translation_function ) ); + } + + foreach ( $argument_assertions as $argument_assertion_context ) { + if ( empty( $argument_assertion_context['tokens'][0] ) ) { + $argument_assertion_context['stack_ptr'] = $func_open_paren_token; + } else { + $argument_assertion_context['stack_ptr'] = $argument_assertion_context['tokens'][0]['token_index']; + } + call_user_func( array( $this, 'check_argument_tokens' ), $phpcs_file, $argument_assertion_context ); + } + + // For _n*() calls, compare the singular and plural strings. + if ( false !== strpos( $this->i18n_functions[ $translation_function ], 'number' ) ) { + $single_context = $argument_assertions[0]; + $plural_context = $argument_assertions[1]; + + $this->compare_single_and_plural_arguments( $phpcs_file, $stack_ptr, $single_context, $plural_context ); + } + } + + /** + * Check if supplied tokens represent a translation text string literal. + * + * @param PHP_CodeSniffer_File $phpcs_file The file being scanned. + * @param array $context Context (@todo needs better description). + * @return bool + */ + protected function check_argument_tokens( PHP_CodeSniffer_File $phpcs_file, $context ) { + $stack_ptr = $context['stack_ptr']; + $tokens = $context['tokens']; + $arg_name = $context['arg_name']; + $method = empty( $context['warning'] ) ? 'addError' : 'addWarning'; + $content = $tokens[0]['content']; + + if ( 0 === count( $tokens ) ) { + $code = 'MissingArg' . ucfirst( $arg_name ); + if ( 'domain' !== $arg_name || ! empty( $this->text_domain ) ) { + $phpcs_file->$method( 'Missing $%s arg.', $stack_ptr, $code, array( $arg_name ) ); + } + return false; + } + if ( count( $tokens ) > 1 ) { + $contents = ''; + foreach ( $tokens as $token ) { + $contents .= $token['content']; + } + $code = 'NonSingularStringLiteral' . ucfirst( $arg_name ); + $phpcs_file->$method( 'The $%s arg must be a single string literal, not "%s".', $stack_ptr, $code, array( $arg_name, $contents ) ); + return false; + } + + if ( in_array( $arg_name, array( 'text', 'single', 'plural' ), true ) ) { + $this->check_text( $phpcs_file, $context ); + } + + if ( T_CONSTANT_ENCAPSED_STRING === $tokens[0]['code'] ) { + if ( 'domain' === $arg_name && ! empty( $this->text_domain ) && trim( $content, '\'""' ) !== $this->text_domain ) { + $phpcs_file->$method( 'Mismatch text domain. Expected \'%s\' but got %s.', $stack_ptr, 'TextDomainMismatch', array( $this->text_domain, $content ) ); + return false; + } + return true; + } + if ( T_DOUBLE_QUOTED_STRING === $tokens[0]['code'] ) { + $interpolated_variables = $this->get_interpolated_variables( $content ); + foreach ( $interpolated_variables as $interpolated_variable ) { + $code = 'InterpolatedVariable' . ucfirst( $arg_name ); + $phpcs_file->$method( 'The $%s arg must not contain interpolated variables. Found "$%s".', $stack_ptr, $code, array( $arg_name, $interpolated_variable ) ); + } + if ( ! empty( $interpolated_variables ) ) { + return false; + } + if ( 'domain' === $arg_name && ! empty( $this->text_domain ) && trim( $content, '\'""' ) !== $this->text_domain ) { + $phpcs_file->$method( 'Mismatch text domain. Expected \'%s\' but got %s.', $stack_ptr, 'TextDomainMismatch', array( $this->text_domain, $content ) ); + return false; + } + return true; + } + + $code = 'NonSingularStringLiteral' . ucfirst( $arg_name ); + $phpcs_file->$method( 'The $%s arg should be single a string literal, not "%s".', $stack_ptr, $code, array( $arg_name, $content ) ); + return false; + } + + /** + * Check for inconsistencies between single and plural arguments. + * + * @param PHP_CodeSniffer_File $phpcs_file The file being scanned. + * @param int $stack_ptr The position of the current token + * in the stack passed in $tokens. + * @param array $single_context Single context (@todo needs better description). + * @param array $plural_context Plural context (@todo needs better description). + * @return void + */ + protected function compare_single_and_plural_arguments( PHP_CodeSniffer_File $phpcs_file, $stack_ptr, $single_context, $plural_context ) { + $single_content = $single_context['tokens'][0]['content']; + $plural_content = $plural_context['tokens'][0]['content']; + + preg_match_all( self::$sprintf_placeholder_regex, $single_content, $single_placeholders ); + $single_placeholders = $single_placeholders[0]; + + preg_match_all( self::$sprintf_placeholder_regex, $plural_content, $plural_placeholders ); + $plural_placeholders = $plural_placeholders[0]; + + // English conflates "singular" with "only one", described in the codex: + // https://codex.wordpress.org/I18n_for_WordPress_Developers#Plurals . + if ( count( $single_placeholders ) < count( $plural_placeholders ) ) { + $error_string = 'Missing singular placeholder, needed for some languages. See https://codex.wordpress.org/I18n_for_WordPress_Developers#Plurals'; + $single_index = $single_context['tokens'][0]['token_index']; + + $phpcs_file->addError( $error_string, $single_index, 'MissingSingularPlaceholder' ); + } + + // Reordering is fine, but mismatched placeholders is probably wrong. + sort( $single_placeholders ); + sort( $plural_placeholders ); + + if ( $single_placeholders !== $plural_placeholders ) { + $phpcs_file->addWarning( 'Mismatched placeholders is probably an error', $stack_ptr, 'MismatchedPlaceholders' ); + } + } + + /** + * Check the string itself for problems. + * + * @param PHP_CodeSniffer_File $phpcs_file The file being scanned. + * @param array $context Context (@todo needs better description). + * @return void + */ + protected function check_text( PHP_CodeSniffer_File $phpcs_file, $context ) { + $stack_ptr = $context['stack_ptr']; + $arg_name = $context['arg_name']; + $content = $context['tokens'][0]['content']; + $fixable_method = empty( $context['warning'] ) ? 'addFixableError' : 'addFixableWarning'; + + // UnorderedPlaceholders: Check for multiple unordered placeholders. + preg_match_all( self::$unordered_sprintf_placeholder_regex, $content, $unordered_matches ); + $unordered_matches = $unordered_matches[0]; + $unordered_matches_count = count( $unordered_matches ); + + if ( $unordered_matches_count >= 2 ) { + $code = 'UnorderedPlaceholders' . ucfirst( $arg_name ); + + $suggestions = array(); + for ( $i = 0; $i < $unordered_matches_count; $i++ ) { + $suggestions[ $i ] = substr_replace( $unordered_matches[ $i ], ( $i + 1 ) . '$', 1, 0 ); + } + + $fix = $phpcs_file->$fixable_method( + 'Multiple placeholders should be ordered. Expected \'%s\', but got %s.', + $stack_ptr, + 'UnorderedPlaceholders', + array( join( ', ', $suggestions ), join( ',', $unordered_matches ) ) + ); + + if ( true === $fix ) { + $fixed_str = str_replace( $unordered_matches, $suggestions, $content ); + + $phpcs_file->fixer->beginChangeset(); + $phpcs_file->fixer->replaceToken( $stack_ptr, $fixed_str ); + $phpcs_file->fixer->endChangeset(); + } + } + + /* + * NoEmptyStrings. + * + * Strip placeholders and surrounding quotes. + */ + $non_placeholder_content = trim( $content, "'" ); + $non_placeholder_content = preg_replace( self::$sprintf_placeholder_regex, '', $non_placeholder_content ); + + if ( empty( $non_placeholder_content ) ) { + $phpcs_file->addError( 'Strings should have translatable content', $stack_ptr, 'NoEmptyStrings' ); + } + } // end check_text() + +} diff --git a/WordPress/Sniffs/WP/PreparedSQLSniff.php b/WordPress/Sniffs/WP/PreparedSQLSniff.php index 97be02e90b..3759a93b48 100644 --- a/WordPress/Sniffs/WP/PreparedSQLSniff.php +++ b/WordPress/Sniffs/WP/PreparedSQLSniff.php @@ -1,11 +1,22 @@ true, - 'get_col' => true, - 'get_row' => true, + 'get_var' => true, + 'get_col' => true, + 'get_row' => true, 'get_results' => true, - 'prepare' => true, - 'query' => true, + 'prepare' => true, + 'query' => true, ); /** @@ -33,16 +44,16 @@ class WordPress_Sniffs_WP_PreparedSQLSniff extends WordPress_Sniff { * @var array */ protected $ignored_tokens = array( - T_OBJECT_OPERATOR => true, - T_OPEN_PARENTHESIS => true, - T_CLOSE_PARENTHESIS => true, - T_WHITESPACE => true, - T_STRING_CONCAT => true, + T_OBJECT_OPERATOR => true, + T_OPEN_PARENTHESIS => true, + T_CLOSE_PARENTHESIS => true, + T_WHITESPACE => true, + T_STRING_CONCAT => true, T_CONSTANT_ENCAPSED_STRING => true, - T_OPEN_SQUARE_BRACKET => true, - T_CLOSE_SQUARE_BRACKET => true, - T_COMMA => true, - T_LNUMBER => true, + T_OPEN_SQUARE_BRACKET => true, + T_CLOSE_SQUARE_BRACKET => true, + T_COMMA => true, + T_LNUMBER => true, ); /** @@ -83,25 +94,23 @@ public function register() { /** * Processes this test, when one of its tokens is encountered. * - * @since 0.8.0 - * * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. * @param int $stackPtr The position of the current token * in the stack passed in $tokens. * + * @since 0.8.0 + * * @return int|void */ public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) { - $tokens = $phpcsFile->getTokens(); + $this->init( $phpcsFile ); // Check for $wpdb variable. - if ( '$wpdb' !== $tokens[ $stackPtr ]['content'] ) { + if ( '$wpdb' !== $this->tokens[ $stackPtr ]['content'] ) { return; } - $this->init( $phpcsFile ); - if ( ! $this->is_wpdb_method_call( $stackPtr ) ) { return; } @@ -112,14 +121,14 @@ public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) { for ( $this->i; $this->i < $this->end; $this->i++ ) { - if ( isset( $this->ignored_tokens[ $tokens[ $this->i ]['code'] ] ) ) { + if ( isset( $this->ignored_tokens[ $this->tokens[ $this->i ]['code'] ] ) ) { continue; } - if ( T_DOUBLE_QUOTED_STRING === $tokens[ $this->i ]['code'] ) { + if ( T_DOUBLE_QUOTED_STRING === $this->tokens[ $this->i ]['code'] ) { $bad_variables = array_filter( - $this->get_interpolated_variables( $tokens[ $this->i ]['content'] ), + $this->get_interpolated_variables( $this->tokens[ $this->i ]['content'] ), create_function( '$symbol', 'return ! in_array( $symbol, array( "wpdb" ), true );' ) // Replace this with closure once 5.3 is minimum requirement. ); @@ -130,29 +139,29 @@ public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) { 'NotPrepared', array( $bad_variable, - $tokens[ $this->i ]['content'] + $this->tokens[ $this->i ]['content'], ) ); } continue; } - if ( T_VARIABLE === $tokens[ $this->i ]['code'] ) { - if ( '$wpdb' === $tokens[ $this->i ]['content'] ) { + if ( T_VARIABLE === $this->tokens[ $this->i ]['code'] ) { + if ( '$wpdb' === $this->tokens[ $this->i ]['content'] ) { $this->is_wpdb_method_call( $this->i ); continue; } } - if ( T_STRING === $tokens[ $this->i ]['code'] ) { + if ( T_STRING === $this->tokens[ $this->i ]['code'] ) { if ( - isset( self::$SQLEscapingFunctions[ $tokens[ $this->i ]['content'] ] ) - || isset( self::$SQLAutoEscapedFunctions[ $tokens[ $this->i ]['content'] ] ) + isset( self::$SQLEscapingFunctions[ $this->tokens[ $this->i ]['content'] ] ) + || isset( self::$SQLAutoEscapedFunctions[ $this->tokens[ $this->i ]['content'] ] ) ) { // Find the opening parenthesis. - $opening_paren = $this->phpcsFile->findNext( T_WHITESPACE, $this->i + 1, null, true, null, true ); + $opening_paren = $this->phpcsFile->findNext( T_WHITESPACE, ( $this->i + 1 ), null, true, null, true ); if ( $opening_paren @@ -163,8 +172,7 @@ public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) { $this->i = $this->tokens[ $opening_paren ]['parenthesis_closer']; continue; } - - } elseif ( isset( self::$formattingFunctions[ $tokens[ $this->i ]['content'] ] ) ) { + } elseif ( isset( self::$formattingFunctions[ $this->tokens[ $this->i ]['content'] ] ) ) { continue; } } @@ -173,7 +181,7 @@ public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) { 'Use placeholders and $wpdb->prepare(); found %s', $this->i, 'NotPrepared', - array( $tokens[ $this->i ]['content'] ) + array( $this->tokens[ $this->i ]['content'] ) ); } @@ -199,16 +207,16 @@ public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) { protected function is_wpdb_method_call( $stackPtr ) { // Check that this is a method call. - $is_object_call = $this->phpcsFile->findNext( array( T_OBJECT_OPERATOR ), $stackPtr + 1, null, null, null, true ); + $is_object_call = $this->phpcsFile->findNext( array( T_OBJECT_OPERATOR ), ( $stackPtr + 1 ), null, null, null, true ); if ( false === $is_object_call ) { return false; } - $methodPtr = $this->phpcsFile->findNext( array( T_WHITESPACE ), $is_object_call + 1, null, true, null, true ); + $methodPtr = $this->phpcsFile->findNext( array( T_WHITESPACE ), ( $is_object_call + 1 ), null, true, null, true ); $method = $this->tokens[ $methodPtr ]['content']; // Find the opening parenthesis. - $opening_paren = $this->phpcsFile->findNext( T_WHITESPACE, $methodPtr + 1, null, true, null, true ); + $opening_paren = $this->phpcsFile->findNext( T_WHITESPACE, ( $methodPtr + 1 ), null, true, null, true ); if ( ! $opening_paren ) { return false; @@ -233,6 +241,6 @@ protected function is_wpdb_method_call( $stackPtr ) { } return true; - } + } // is_wpdb_method_call() -} // end class. +} // End class. diff --git a/WordPress/Sniffs/WhiteSpace/CastStructureSpacingSniff.php b/WordPress/Sniffs/WhiteSpace/CastStructureSpacingSniff.php index 0c3249b472..ab2f91cae9 100755 --- a/WordPress/Sniffs/WhiteSpace/CastStructureSpacingSniff.php +++ b/WordPress/Sniffs/WhiteSpace/CastStructureSpacingSniff.php @@ -1,91 +1,77 @@ - * @author Marc McIntyre - * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600) - * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence - * @link http://pear.php.net/package/PHP_CodeSniffer + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ /** - * Squiz_Sniffs_WhiteSpace_CastSpacingSniff. + * Ensure cast statements don't contain whitespace, but *are* surrounded by whitespace, based upon Squiz code. + * + * @link https://make.wordpress.org/core/handbook/best-practices/coding-standards/php/#space-usage + * + * @package WPCS\WordPressCodingStandards * - * Ensure cast statements don't contain whitespace. + * @since 0.3.0 * - * @category PHP - * @package PHP_CodeSniffer - * @author Greg Sherwood - * @author Marc McIntyre - * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600) - * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence - * @version Release: @package_version@ - * @link http://pear.php.net/package/PHP_CodeSniffer + * Last synced with base class ?[unknown date]? at commit ?[unknown commit]?. + * @link https://github.com/squizlabs/PHP_CodeSniffer/blob/master/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/CastSpacingSniff.php */ -class WordPress_Sniffs_WhiteSpace_CastStructureSpacingSniff implements PHP_CodeSniffer_Sniff -{ - - /** - * Returns an array of tokens this test wants to listen for. - * - * @return array - */ - public function register() - { - return PHP_CodeSniffer_Tokens::$castTokens; - - }//end register() +class WordPress_Sniffs_WhiteSpace_CastStructureSpacingSniff implements PHP_CodeSniffer_Sniff { + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + return PHP_CodeSniffer_Tokens::$castTokens; - /** - * Processes this test, when one of its tokens is encountered. - * - * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. - * @param int $stackPtr The position of the current token in the - * stack passed in $tokens. - * - * @return void - */ - public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) - { - $tokens = $phpcsFile->getTokens(); + } - $content = $tokens[$stackPtr]['content']; - $expected = str_replace(' ', '', $content); - $expected = str_replace("\t", '', $expected); + /** + * Processes this test, when one of its tokens is encountered. + * + * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) { + $tokens = $phpcsFile->getTokens(); - if ($content !== $expected) { - $error = 'Cast statements must not contain whitespace; expected "%s" but found "%s"'; - $data = array( - $expected, - $content, - ); - $phpcsFile->addWarning($error, $stackPtr, 'ContainsWhiteSpace', $data); - } + $content = $tokens[ $stackPtr ]['content']; + $expected = str_replace( ' ', '', $content ); + $expected = str_replace( "\t", '', $expected ); - if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE) { - $error = 'No space before opening casting parenthesis is prohibited'; - $phpcsFile->addWarning($error, $stackPtr, 'NoSpaceBeforeOpenParenthesis'); - } + if ( $content !== $expected ) { + $error = 'Cast statements must not contain whitespace; expected "%s" but found "%s"'; + $data = array( + $expected, + $content, + ); + $phpcsFile->addWarning( $error, $stackPtr, 'ContainsWhiteSpace', $data ); + } - if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { - $error = 'No space after closing casting parenthesis is prohibited'; - $phpcsFile->addWarning($error, $stackPtr, 'NoSpaceAfterCloseParenthesis'); - } - }//end process() + if ( T_WHITESPACE !== $tokens[ ( $stackPtr - 1 ) ]['code'] ) { + $error = 'No space before opening casting parenthesis is prohibited'; + $phpcsFile->addWarning( $error, $stackPtr, 'NoSpaceBeforeOpenParenthesis' ); + } - /** - * If true, an error will be thrown; otherwise a warning. - * - * @var bool - */ - public $error = false; + if ( T_WHITESPACE !== $tokens[ ( $stackPtr + 1 ) ]['code'] ) { + $error = 'No space after closing casting parenthesis is prohibited'; + $phpcsFile->addWarning( $error, $stackPtr, 'NoSpaceAfterCloseParenthesis' ); + } + } // end process() -}//end class + /** + * If true, an error will be thrown; otherwise a warning. + * + * @var bool + */ + public $error = false; -?> +} // End class. diff --git a/WordPress/Sniffs/WhiteSpace/ControlStructureSpacingSniff.php b/WordPress/Sniffs/WhiteSpace/ControlStructureSpacingSniff.php index c6dac82308..af6cbc56f2 100644 --- a/WordPress/Sniffs/WhiteSpace/ControlStructureSpacingSniff.php +++ b/WordPress/Sniffs/WhiteSpace/ControlStructureSpacingSniff.php @@ -1,60 +1,59 @@ - * @author Greg Sherwood - * @author Marc McIntyre + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ /** - * Squiz_Sniffs_WhiteSpace_ControlStructureSpacingSniff. + * Enforces spacing around logical operators and assignments, based upon Squiz code. + * + * @package WPCS\WordPressCodingStandards * - * Checks that any array declarations are lower case. + * @since 0.1.0 + * @since 2013-06-11 This sniff no longer supports JS. + * @since 0.3.0 This sniff now has the ability to fix most errors it flags. + * @since 0.7.0 This class now extends WordPress_Sniff. * - * @category PHP - * @package PHP_CodeSniffer - * @author John Godley - * @author Greg Sherwood - * @author Marc McIntyre + * Last synced with base class ?[unknown date]? at commit ?[unknown commit]?. + * @link https://github.com/squizlabs/PHP_CodeSniffer/blob/master/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/ControlStructureSpacingSniff.php */ class WordPress_Sniffs_WhiteSpace_ControlStructureSpacingSniff extends WordPress_Sniff { - /** - * A list of tokenizers this sniff supports. - * - * @var array - */ - public $supportedTokenizers = array( 'PHP' ); - - /** - * Check for blank lines on start/end of control structures - * @var boolean - */ - public $blank_line_check = false; - - /** - * Check for blank lines after control structures. - * - * @var boolean - */ - public $blank_line_after_check = true; - - /** - * Require for space before T_COLON when using the alternative syntax for control structures - * - * @var string one of 'required', 'forbidden', optional' - */ - public $space_before_colon = 'required'; + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = array( 'PHP' ); + + /** + * Check for blank lines on start/end of control structures. + * + * @var boolean + */ + public $blank_line_check = false; + + /** + * Check for blank lines after control structures. + * + * @var boolean + */ + public $blank_line_after_check = true; + + /** + * Require for space before T_COLON when using the alternative syntax for control structures. + * + * @var string one of 'required', 'forbidden', optional' + */ + public $space_before_colon = 'required'; /** * How many spaces should be between a T_CLOSURE and T_OPEN_PARENTHESIS. * - * function[*]() {...} + * `function[*]() {...}` * * @since 0.7.0 * @@ -62,481 +61,469 @@ class WordPress_Sniffs_WhiteSpace_ControlStructureSpacingSniff extends WordPress */ public $spaces_before_closure_open_paren = -1; - /** - * Returns an array of tokens this test wants to listen for. - * - * @return array - */ - public function register() - { - return array( - T_IF, - T_WHILE, - T_FOREACH, - T_FOR, - T_SWITCH, - T_DO, - T_ELSE, - T_ELSEIF, - T_FUNCTION, - T_CLOSURE, - T_USE, - ); - - }//end register() - - - /** - * Processes this test, when one of its tokens is encountered. - * - * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. - * @param int $stackPtr The position of the current token in the - * stack passed in $tokens. - * - * @return void - */ - public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) - { - $this->blank_line_check = (bool) $this->blank_line_check; - $this->blank_line_after_check = (bool) $this->blank_line_after_check; - - $tokens = $phpcsFile->getTokens(); - - $this->init( $phpcsFile ); - - if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE - && ! ( $tokens[$stackPtr]['code'] === T_ELSE && $tokens[($stackPtr + 1)]['code'] === T_COLON ) - && ! ( - T_CLOSURE === $tokens[ $stackPtr ]['code'] - && ( - 0 === (int) $this->spaces_before_closure_open_paren - || -1 === (int) $this->spaces_before_closure_open_paren - ) - ) - ) { - $error = 'Space after opening control structure is required'; - if (isset($phpcsFile->fixer) === true) { - $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceAfterStructureOpen'); - if ($fix === true) { - $phpcsFile->fixer->beginChangeset(); - $phpcsFile->fixer->addContent($stackPtr, ' '); - $phpcsFile->fixer->endChangeset(); - } - } else { - $phpcsFile->addError($error, $stackPtr, 'NoSpaceAfterStructureOpen'); - } - } - - if ( isset( $tokens[ $stackPtr ]['scope_closer'] ) === false ) { - - if ( T_USE === $tokens[ $stackPtr ]['code'] && 'closure' === $this->get_use_type( $stackPtr ) ) { - $scopeOpener = $phpcsFile->findNext( T_OPEN_CURLY_BRACKET, $stackPtr + 1 ); - $scopeCloser = $tokens[ $scopeOpener ]['scope_closer']; - } else { - return; - } - - } else { - $scopeOpener = $tokens[ $stackPtr ]['scope_opener']; - $scopeCloser = $tokens[ $stackPtr ]['scope_closer']; - } - - // alternative syntax - if ( $tokens[$scopeOpener]['code'] === T_COLON ) { - - if ( $this->space_before_colon === 'required') { - - if ( $tokens[$scopeOpener - 1]['code'] !== T_WHITESPACE ) { - $error = 'Space between opening control structure and T_COLON is required'; - - if ( isset($phpcsFile->fixer) === true ) { - $fix = $phpcsFile->addFixableError($error, $scopeOpener, 'NoSpaceBetweenStructureColon'); - - if ($fix === true) { - $phpcsFile->fixer->beginChangeset(); - $phpcsFile->fixer->addContentBefore($scopeOpener, ' '); - $phpcsFile->fixer->endChangeset(); - } - } else { - $phpcsFile->addError($error, $stackPtr, 'NoSpaceBetweenStructureColon'); - } - } - - } elseif ( $this->space_before_colon === 'forbidden' ) { - - if ( $tokens[$scopeOpener - 1]['code'] === T_WHITESPACE ) { - $error = 'Extra space between opening control structure and T_COLON found'; - - if ( isset($phpcsFile->fixer) === true ) { - $fix = $phpcsFile->addFixableError( $error, $scopeOpener - 1, 'SpaceBetweenStructureColon' ); - - if ($fix === true) { - $phpcsFile->fixer->beginChangeset(); - $phpcsFile->fixer->replaceToken( $scopeOpener - 1, '' ); - $phpcsFile->fixer->endChangeset(); - } - } else { - $phpcsFile->addError( $error, $stackPtr, 'SpaceBetweenStructureColon' ); - } - } - } - } - - $parenthesisOpener = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr + 1), null, true); - - // If this is a function declaration. - if ( $tokens[ $stackPtr ]['code'] === T_FUNCTION ) { - - if ( $tokens[ $parenthesisOpener ]['code'] === T_STRING ) { - - $function_name_ptr = $parenthesisOpener; - - } elseif ( $tokens[ $parenthesisOpener ]['code'] === T_BITWISE_AND ) { - - // This function returns by reference (function &function_name() {}). - $function_name_ptr = $parenthesisOpener = $phpcsFile->findNext( - PHP_CodeSniffer_Tokens::$emptyTokens, - $parenthesisOpener + 1, - null, - true - ); - } - - $parenthesisOpener = $phpcsFile->findNext( - PHP_CodeSniffer_Tokens::$emptyTokens, - $parenthesisOpener + 1, - null, - true - ); - - // Checking this: function my_function[*](...) {} - if ( $parenthesisOpener !== $function_name_ptr + 1 ) { - - $error = 'Space between function name and opening parenthesis is prohibited.'; - $fix = $phpcsFile->addFixableError( - $error, - $stackPtr, - 'SpaceBeforeFunctionOpenParenthesis', - $tokens[ $function_name_ptr + 1 ]['content'] - ); - - if ( true === $fix ) { - $phpcsFile->fixer->beginChangeset(); - $phpcsFile->fixer->replaceToken( $function_name_ptr + 1, '' ); - $phpcsFile->fixer->endChangeset(); - } - } - - } elseif ( T_CLOSURE === $tokens[ $stackPtr ]['code'] ) { - - // Check if there is a use () statement. - if ( isset( $tokens[ $parenthesisOpener ]['parenthesis_closer'] ) ) { - - $usePtr = $phpcsFile->findNext( - PHP_CodeSniffer_Tokens::$emptyTokens, - $tokens[ $parenthesisOpener ]['parenthesis_closer'] + 1, - null, - true, - null, - true - ); - - // If it is, we set that as the "scope opener". - if ( T_USE === $tokens[ $usePtr ]['code'] ) { - $scopeOpener = $usePtr; - } - } - } - - if ( - T_COLON !== $tokens[ $parenthesisOpener ]['code'] - && T_FUNCTION !== $tokens[ $stackPtr ]['code'] - ) { - - if ( - T_CLOSURE === $tokens[ $stackPtr ]['code'] - && 0 === (int) $this->spaces_before_closure_open_paren - ) { - - if ( ($stackPtr + 1) !== $parenthesisOpener ) { - // Checking this: function[*](...) {}. - $error = 'Space before closure opening parenthesis is prohibited'; - $fix = $phpcsFile->addFixableError( $error, $stackPtr, 'SpaceBeforeClosureOpenParenthesis' ); - if ( $fix === true ) { - $phpcsFile->fixer->beginChangeset(); - $phpcsFile->fixer->replaceToken( $stackPtr + 1, '' ); - $phpcsFile->fixer->endChangeset(); - } - } - - } elseif ( - ( - T_CLOSURE !== $tokens[ $stackPtr ]['code'] - || 1 === (int) $this->spaces_before_closure_open_paren - ) - && ($stackPtr + 1) === $parenthesisOpener - ) { - - // Checking this: if[*](...) {}. - $error = 'No space before opening parenthesis is prohibited'; - if ( isset( $phpcsFile->fixer ) === true ) { - $fix = $phpcsFile->addFixableError( $error, $stackPtr, 'NoSpaceBeforeOpenParenthesis' ); - if ( $fix === true ) { - $phpcsFile->fixer->beginChangeset(); - $phpcsFile->fixer->addContent( $stackPtr, ' ' ); - $phpcsFile->fixer->endChangeset(); - } - } else { - $phpcsFile->addError( $error, $stackPtr, 'NoSpaceBeforeOpenParenthesis' ); - } - } - } - - if ( - T_WHITESPACE === $tokens[ $stackPtr + 1 ]['code'] - && ' ' !== $tokens[ $stackPtr + 1 ]['content'] - ) { - // Checking this: if [*](...) {}. - $error = 'Expected exactly one space before opening parenthesis; "%s" found.'; - $fix = $phpcsFile->addFixableError( - $error, - $stackPtr, - 'ExtraSpaceBeforeOpenParenthesis', - $tokens[ $stackPtr + 1 ]['content'] - ); - - if ( true === $fix ) { - $phpcsFile->fixer->beginChangeset(); - $phpcsFile->fixer->replaceToken( $stackPtr + 1, ' ' ); - $phpcsFile->fixer->endChangeset(); - } - } - - if ($tokens[($parenthesisOpener + 1)]['code'] !== T_WHITESPACE - && $tokens[($parenthesisOpener + 1)]['code'] !== T_CLOSE_PARENTHESIS - ) { - // Checking this: $value = my_function([*]...). - $error = 'No space after opening parenthesis is prohibited'; - if (isset($phpcsFile->fixer) === true) { - $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceAfterOpenParenthesis'); - if ($fix === true) { - $phpcsFile->fixer->beginChangeset(); - $phpcsFile->fixer->addContent($parenthesisOpener, ' '); - $phpcsFile->fixer->endChangeset(); - } - } else { - $phpcsFile->addError($error, $stackPtr, 'NoSpaceAfterOpenParenthesis'); - } - } - - if ( isset($tokens[$parenthesisOpener]['parenthesis_closer']) === true ) { - - $parenthesisCloser = $tokens[$parenthesisOpener]['parenthesis_closer']; - - if ( $tokens[($parenthesisOpener + 1)]['code'] !== T_CLOSE_PARENTHESIS ) { - - if ($tokens[($parenthesisCloser - 1)]['code'] !== T_WHITESPACE) { - $error = 'No space before closing parenthesis is prohibited'; - if (isset($phpcsFile->fixer) === true) { - $fix = $phpcsFile->addFixableError($error, $parenthesisCloser, 'NoSpaceBeforeCloseParenthesis'); - if ($fix === true) { - $phpcsFile->fixer->beginChangeset(); - $phpcsFile->fixer->addContentBefore($parenthesisCloser, ' '); - $phpcsFile->fixer->endChangeset(); - } - } else { - $phpcsFile->addError($error, $parenthesisCloser, 'NoSpaceBeforeCloseParenthesis'); - } - } - - if ( - $tokens[ $parenthesisCloser + 1 ]['code'] !== T_WHITESPACE - && $tokens[ $scopeOpener ]['code'] !== T_COLON - ) { - $error = 'Space between opening control structure and closing parenthesis is required'; - - if ( isset( $phpcsFile->fixer ) === true ) { - $fix = $phpcsFile->addFixableError( $error, $scopeOpener, 'NoSpaceAfterCloseParenthesis' ); - - if ( $fix === true ) { - $phpcsFile->fixer->beginChangeset(); - $phpcsFile->fixer->addContentBefore( $scopeOpener, ' ' ); - $phpcsFile->fixer->endChangeset(); - } - } else { - $phpcsFile->addError( $error, $stackPtr, 'NoSpaceAfterCloseParenthesis' ); - } - } - } - - if (isset($tokens[$parenthesisOpener]['parenthesis_owner']) === true - && $tokens[$parenthesisCloser]['line'] !== $tokens[$scopeOpener]['line'] - ) { - $error = 'Opening brace should be on the same line as the declaration'; - if (isset($phpcsFile->fixer) === true) { - $fix = $phpcsFile->addFixableError($error, $parenthesisOpener, 'OpenBraceNotSameLine'); - if ($fix === true) { - $phpcsFile->fixer->beginChangeset(); - - for ($i = ($parenthesisCloser + 1); $i < $scopeOpener; $i++) { - $phpcsFile->fixer->replaceToken($i, ''); - } - - $phpcsFile->fixer->addContent($parenthesisCloser, ' '); - $phpcsFile->fixer->endChangeset(); - } - } else { - $phpcsFile->addError($error, $parenthesisOpener, 'OpenBraceNotSameLine'); - }//end if - return; - - } elseif ( - T_WHITESPACE === $tokens[ $parenthesisCloser + 1 ]['code'] - && ' ' !== $tokens[ $parenthesisCloser + 1 ]['content'] - ) { - - // Checking this: if (...) [*]{} - $error = 'Expected exactly one space between closing parenthesis and opening control structure; "%s" found.'; - $fix = $phpcsFile->addFixableError( - $error, - $stackPtr, - 'ExtraSpaceAfterCloseParenthesis', - $tokens[ $parenthesisCloser + 1 ]['content'] - ); - - if ( true === $fix ) { - $phpcsFile->fixer->beginChangeset(); - $phpcsFile->fixer->replaceToken( $parenthesisCloser + 1, ' ' ); - $phpcsFile->fixer->endChangeset(); - } - } - }//end if - - if ($this->blank_line_check === true) { - $firstContent = $phpcsFile->findNext(T_WHITESPACE, ($scopeOpener + 1), null, true); - if ($tokens[$firstContent]['line'] > ($tokens[$scopeOpener]['line'] + 1) - && in_array($tokens[$firstContent]['code'], array(T_CLOSE_TAG, T_COMMENT)) === false - ) { - $error = 'Blank line found at start of control structure'; - if (isset($phpcsFile->fixer) === true) { - $fix = $phpcsFile->addFixableError($error, $scopeOpener, 'BlankLineAfterStart'); - if ($fix === true) { - $phpcsFile->fixer->beginChangeset(); - - for ($i = ($scopeOpener + 1); $i < $firstContent; $i++) { - $phpcsFile->fixer->replaceToken($i, ''); - } - - $phpcsFile->fixer->addNewline($scopeOpener); - $phpcsFile->fixer->endChangeset(); - } - } else { - $phpcsFile->addError($error, $scopeOpener, 'BlankLineAfterStart'); - } - } - - $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($scopeCloser - 1), null, true); - if ($tokens[$lastContent]['line'] !== ($tokens[$scopeCloser]['line'] - 1)) { - $errorToken = $scopeCloser; - for ($i = ($scopeCloser - 1); $i > $lastContent; $i--) { - if ($tokens[$i]['line'] < $tokens[$scopeCloser]['line'] - && $tokens[$firstContent]['code'] !== T_OPEN_TAG - ) { - // TODO: Reporting error at empty line won't highlight it in IDE. - $error = 'Blank line found at end of control structure'; - if (isset($phpcsFile->fixer) === true) { - $fix = $phpcsFile->addFixableError($error, $i, 'BlankLineBeforeEnd'); - if ($fix === true) { - $phpcsFile->fixer->beginChangeset(); - - for ($j = ($lastContent + 1); $j < $scopeCloser; $j++) { - $phpcsFile->fixer->replaceToken($j, ''); - } - - $phpcsFile->fixer->addNewlineBefore($scopeCloser); - $phpcsFile->fixer->endChangeset(); - } - } else { - $phpcsFile->addError($error, $i, 'BlankLineBeforeEnd'); - }//end if - break; - }//end if - }//end for - }//end if - }//end if - - $trailingContent = $phpcsFile->findNext(T_WHITESPACE, ($scopeCloser + 1), null, true); - if ($tokens[$trailingContent]['code'] === T_ELSE) { - if ($tokens[$stackPtr]['code'] === T_IF) { - // IF with ELSE. - return; - } - } - - if ($tokens[$trailingContent]['code'] === T_COMMENT) { - if ($tokens[$trailingContent]['line'] === $tokens[$scopeCloser]['line']) { - if (substr($tokens[$trailingContent]['content'], 0, 5) === '//end') { - // There is an end comment, so we have to get the next piece - // of content. - $trailingContent = $phpcsFile->findNext(T_WHITESPACE, ($trailingContent + 1), null, true); - } - } - } - - if ($tokens[$trailingContent]['code'] === T_BREAK) { - // If this BREAK is closing a CASE, we don't need the - // blank line after this control structure. - if (isset($tokens[$trailingContent]['scope_condition']) === true) { - $condition = $tokens[$trailingContent]['scope_condition']; - if ($tokens[$condition]['code'] === T_CASE || $tokens[$condition]['code'] === T_DEFAULT) { - return; - } - } - } - - if ($tokens[$trailingContent]['code'] === T_CLOSE_TAG) { - // At the end of the script or embedded code. - return; - } - - if ($tokens[$trailingContent]['code'] === T_CLOSE_CURLY_BRACKET) { - // Another control structure's closing brace. - if (isset($tokens[$trailingContent]['scope_condition']) === true) { - $owner = $tokens[$trailingContent]['scope_condition']; - if ($tokens[$owner]['code'] === T_FUNCTION) { - // The next content is the closing brace of a function - // so normal function rules apply and we can ignore it. - return; - } - } - - if ($this->blank_line_after_check === true - && $tokens[$trailingContent]['line'] != ($tokens[$scopeCloser]['line'] + 1) - ) { - // TODO: Won't cover following case: "} echo 'OK';". - $error = 'Blank line found after control structure'; - if (isset($phpcsFile->fixer) === true) { - $fix = $phpcsFile->addFixableError($error, $scopeCloser, 'BlankLineAfterEnd'); - if ($fix === true) { - $phpcsFile->fixer->beginChangeset(); - - for ($i = ($scopeCloser + 1); $i < $trailingContent; $i++) { - $phpcsFile->fixer->replaceToken($i, ''); - } - - // TODO: Instead a separate error should be triggered when content comes right after closing brace. - $phpcsFile->fixer->addNewlineBefore($trailingContent); - $phpcsFile->fixer->endChangeset(); - } - } else { - $phpcsFile->addError($error, $scopeCloser, 'BlankLineAfterEnd'); - } - } - }//end if - - }//end process() - - -}//end class - -?> + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + return array( + T_IF, + T_WHILE, + T_FOREACH, + T_FOR, + T_SWITCH, + T_DO, + T_ELSE, + T_ELSEIF, + T_FUNCTION, + T_CLOSURE, + T_USE, + ); + + } + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) { + $this->blank_line_check = (bool) $this->blank_line_check; + $this->blank_line_after_check = (bool) $this->blank_line_after_check; + + $this->init( $phpcsFile ); + + if ( isset( $this->tokens[ ( $stackPtr + 1 ) ] ) && T_WHITESPACE !== $this->tokens[ ( $stackPtr + 1 ) ]['code'] + && ! ( T_ELSE === $this->tokens[ $stackPtr ]['code'] && T_COLON === $this->tokens[ ( $stackPtr + 1 ) ]['code'] ) + && ! ( + T_CLOSURE === $this->tokens[ $stackPtr ]['code'] + && ( + 0 === (int) $this->spaces_before_closure_open_paren + || -1 === (int) $this->spaces_before_closure_open_paren + ) + ) + ) { + $error = 'Space after opening control structure is required'; + if ( isset( $phpcsFile->fixer ) ) { + $fix = $phpcsFile->addFixableError( $error, $stackPtr, 'NoSpaceAfterStructureOpen' ); + if ( true === $fix ) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent( $stackPtr, ' ' ); + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->addError( $error, $stackPtr, 'NoSpaceAfterStructureOpen' ); + } + } + + if ( ! isset( $this->tokens[ $stackPtr ]['scope_closer'] ) ) { + + if ( T_USE === $this->tokens[ $stackPtr ]['code'] && 'closure' === $this->get_use_type( $stackPtr ) ) { + $scopeOpener = $phpcsFile->findNext( T_OPEN_CURLY_BRACKET, ( $stackPtr + 1 ) ); + $scopeCloser = $this->tokens[ $scopeOpener ]['scope_closer']; + } else { + return; + } + } else { + $scopeOpener = $this->tokens[ $stackPtr ]['scope_opener']; + $scopeCloser = $this->tokens[ $stackPtr ]['scope_closer']; + } + + // Alternative syntax. + if ( T_COLON === $this->tokens[ $scopeOpener ]['code'] ) { + + if ( 'required' === $this->space_before_colon ) { + + if ( T_WHITESPACE !== $this->tokens[ ( $scopeOpener - 1 ) ]['code'] ) { + $error = 'Space between opening control structure and T_COLON is required'; + + if ( isset( $phpcsFile->fixer ) ) { + $fix = $phpcsFile->addFixableError( $error, $scopeOpener, 'NoSpaceBetweenStructureColon' ); + + if ( true === $fix ) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContentBefore( $scopeOpener, ' ' ); + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->addError( $error, $stackPtr, 'NoSpaceBetweenStructureColon' ); + } + } + } elseif ( 'forbidden' === $this->space_before_colon ) { + + if ( T_WHITESPACE === $this->tokens[ ( $scopeOpener - 1 ) ]['code'] ) { + $error = 'Extra space between opening control structure and T_COLON found'; + + if ( isset( $phpcsFile->fixer ) ) { + $fix = $phpcsFile->addFixableError( $error, ( $scopeOpener - 1 ), 'SpaceBetweenStructureColon' ); + + if ( true === $fix ) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken( ( $scopeOpener - 1 ), '' ); + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->addError( $error, $stackPtr, 'SpaceBetweenStructureColon' ); + } + } + } + } + + $parenthesisOpener = $phpcsFile->findNext( PHP_CodeSniffer_Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true ); + + // If this is a function declaration. + if ( T_FUNCTION === $this->tokens[ $stackPtr ]['code'] ) { + + if ( T_STRING === $this->tokens[ $parenthesisOpener ]['code'] ) { + + $function_name_ptr = $parenthesisOpener; + + } elseif ( T_BITWISE_AND === $this->tokens[ $parenthesisOpener ]['code'] ) { + + // This function returns by reference (function &function_name() {}). + $function_name_ptr = $parenthesisOpener = $phpcsFile->findNext( + PHP_CodeSniffer_Tokens::$emptyTokens, + ( $parenthesisOpener + 1 ), + null, + true + ); + } + + $parenthesisOpener = $phpcsFile->findNext( + PHP_CodeSniffer_Tokens::$emptyTokens, + ( $parenthesisOpener + 1 ), + null, + true + ); + + // Checking this: function my_function[*](...) {}. + if ( ( $function_name_ptr + 1 ) !== $parenthesisOpener ) { + + $error = 'Space between function name and opening parenthesis is prohibited.'; + $fix = $phpcsFile->addFixableError( + $error, + $stackPtr, + 'SpaceBeforeFunctionOpenParenthesis', + $this->tokens[ ( $function_name_ptr + 1 ) ]['content'] + ); + + if ( true === $fix ) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken( ( $function_name_ptr + 1 ), '' ); + $phpcsFile->fixer->endChangeset(); + } + } + } elseif ( T_CLOSURE === $this->tokens[ $stackPtr ]['code'] ) { + + // Check if there is a use () statement. + if ( isset( $this->tokens[ $parenthesisOpener ]['parenthesis_closer'] ) ) { + + $usePtr = $phpcsFile->findNext( + PHP_CodeSniffer_Tokens::$emptyTokens, + ( $this->tokens[ $parenthesisOpener ]['parenthesis_closer'] + 1 ), + null, + true, + null, + true + ); + + // If it is, we set that as the "scope opener". + if ( T_USE === $this->tokens[ $usePtr ]['code'] ) { + $scopeOpener = $usePtr; + } + } + } + + if ( + T_COLON !== $this->tokens[ $parenthesisOpener ]['code'] + && T_FUNCTION !== $this->tokens[ $stackPtr ]['code'] + ) { + + if ( + T_CLOSURE === $this->tokens[ $stackPtr ]['code'] + && 0 === (int) $this->spaces_before_closure_open_paren + ) { + + if ( ( $stackPtr + 1) !== $parenthesisOpener ) { + // Checking this: function[*](...) {}. + $error = 'Space before closure opening parenthesis is prohibited'; + $fix = $phpcsFile->addFixableError( $error, $stackPtr, 'SpaceBeforeClosureOpenParenthesis' ); + if ( true === $fix ) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken( ( $stackPtr + 1 ), '' ); + $phpcsFile->fixer->endChangeset(); + } + } + } elseif ( + ( + T_CLOSURE !== $this->tokens[ $stackPtr ]['code'] + || 1 === (int) $this->spaces_before_closure_open_paren + ) + && ( $stackPtr + 1 ) === $parenthesisOpener + ) { + + // Checking this: if[*](...) {}. + $error = 'No space before opening parenthesis is prohibited'; + if ( isset( $phpcsFile->fixer ) ) { + $fix = $phpcsFile->addFixableError( $error, $stackPtr, 'NoSpaceBeforeOpenParenthesis' ); + if ( true === $fix ) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent( $stackPtr, ' ' ); + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->addError( $error, $stackPtr, 'NoSpaceBeforeOpenParenthesis' ); + } + } + } + + if ( + T_WHITESPACE === $this->tokens[ ( $stackPtr + 1 ) ]['code'] + && ' ' !== $this->tokens[ ( $stackPtr + 1 ) ]['content'] + ) { + // Checking this: if [*](...) {}. + $error = 'Expected exactly one space before opening parenthesis; "%s" found.'; + $fix = $phpcsFile->addFixableError( + $error, + $stackPtr, + 'ExtraSpaceBeforeOpenParenthesis', + $this->tokens[ ( $stackPtr + 1 ) ]['content'] + ); + + if ( true === $fix ) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken( ( $stackPtr + 1 ), ' ' ); + $phpcsFile->fixer->endChangeset(); + } + } + + if ( T_WHITESPACE !== $this->tokens[ ( $parenthesisOpener + 1) ]['code'] + && T_CLOSE_PARENTHESIS !== $this->tokens[ ( $parenthesisOpener + 1) ]['code'] + ) { + // Checking this: $value = my_function([*]...). + $error = 'No space after opening parenthesis is prohibited'; + if ( isset( $phpcsFile->fixer ) ) { + $fix = $phpcsFile->addFixableError( $error, $stackPtr, 'NoSpaceAfterOpenParenthesis' ); + if ( true === $fix ) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent( $parenthesisOpener, ' ' ); + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->addError( $error, $stackPtr, 'NoSpaceAfterOpenParenthesis' ); + } + } + + if ( isset( $this->tokens[ $parenthesisOpener ]['parenthesis_closer'] ) ) { + + $parenthesisCloser = $this->tokens[ $parenthesisOpener ]['parenthesis_closer']; + + if ( T_CLOSE_PARENTHESIS !== $this->tokens[ ( $parenthesisOpener + 1 ) ]['code'] ) { + + if ( T_WHITESPACE !== $this->tokens[ ( $parenthesisCloser - 1 ) ]['code'] ) { + $error = 'No space before closing parenthesis is prohibited'; + if ( isset( $phpcsFile->fixer ) ) { + $fix = $phpcsFile->addFixableError( $error, $parenthesisCloser, 'NoSpaceBeforeCloseParenthesis' ); + if ( true === $fix ) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContentBefore( $parenthesisCloser, ' ' ); + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->addError( $error, $parenthesisCloser, 'NoSpaceBeforeCloseParenthesis' ); + } + } + + if ( + T_WHITESPACE !== $this->tokens[ ( $parenthesisCloser + 1 ) ]['code'] + && T_COLON !== $this->tokens[ $scopeOpener ]['code'] + ) { + $error = 'Space between opening control structure and closing parenthesis is required'; + + if ( isset( $phpcsFile->fixer ) ) { + $fix = $phpcsFile->addFixableError( $error, $scopeOpener, 'NoSpaceAfterCloseParenthesis' ); + + if ( true === $fix ) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContentBefore( $scopeOpener, ' ' ); + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->addError( $error, $stackPtr, 'NoSpaceAfterCloseParenthesis' ); + } + } + } + + if ( isset( $this->tokens[ $parenthesisOpener ]['parenthesis_owner'] ) + && $this->tokens[ $parenthesisCloser ]['line'] !== $this->tokens[ $scopeOpener ]['line'] + ) { + $error = 'Opening brace should be on the same line as the declaration'; + if ( isset( $phpcsFile->fixer ) ) { + $fix = $phpcsFile->addFixableError( $error, $parenthesisOpener, 'OpenBraceNotSameLine' ); + if ( true === $fix ) { + $phpcsFile->fixer->beginChangeset(); + + for ( $i = ( $parenthesisCloser + 1 ); $i < $scopeOpener; $i++ ) { + $phpcsFile->fixer->replaceToken( $i, '' ); + } + + $phpcsFile->fixer->addContent( $parenthesisCloser, ' ' ); + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->addError( $error, $parenthesisOpener, 'OpenBraceNotSameLine' ); + } // end if + return; + + } elseif ( + T_WHITESPACE === $this->tokens[ ( $parenthesisCloser + 1 ) ]['code'] + && ' ' !== $this->tokens[ ( $parenthesisCloser + 1 ) ]['content'] + ) { + + // Checking this: if (...) [*]{}. + $error = 'Expected exactly one space between closing parenthesis and opening control structure; "%s" found.'; + $fix = $phpcsFile->addFixableError( + $error, + $stackPtr, + 'ExtraSpaceAfterCloseParenthesis', + $this->tokens[ ( $parenthesisCloser + 1 ) ]['content'] + ); + + if ( true === $fix ) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken( ( $parenthesisCloser + 1 ), ' ' ); + $phpcsFile->fixer->endChangeset(); + } + } + } // end if + + if ( true === $this->blank_line_check ) { + $firstContent = $phpcsFile->findNext( T_WHITESPACE, ( $scopeOpener + 1 ), null, true ); + if ( $this->tokens[ $firstContent ]['line'] > ( $this->tokens[ $scopeOpener ]['line'] + 1 ) + && false === in_array( $this->tokens[ $firstContent ]['code'], array( T_CLOSE_TAG, T_COMMENT ), true ) + ) { + $error = 'Blank line found at start of control structure'; + if ( isset( $phpcsFile->fixer ) ) { + $fix = $phpcsFile->addFixableError( $error, $scopeOpener, 'BlankLineAfterStart' ); + if ( true === $fix ) { + $phpcsFile->fixer->beginChangeset(); + + for ( $i = ( $scopeOpener + 1 ); $i < $firstContent; $i++ ) { + $phpcsFile->fixer->replaceToken( $i, '' ); + } + + $phpcsFile->fixer->addNewline( $scopeOpener ); + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->addError( $error, $scopeOpener, 'BlankLineAfterStart' ); + } + } + + $lastContent = $phpcsFile->findPrevious( T_WHITESPACE, ( $scopeCloser - 1 ), null, true ); + if ( ( $this->tokens[ $scopeCloser ]['line'] - 1 ) !== $this->tokens[ $lastContent ]['line'] ) { + $errorToken = $scopeCloser; + for ( $i = ( $scopeCloser - 1 ); $i > $lastContent; $i-- ) { + if ( $this->tokens[ $i ]['line'] < $this->tokens[ $scopeCloser ]['line'] + && T_OPEN_TAG !== $this->tokens[ $firstContent ]['code'] + ) { + // TODO: Reporting error at empty line won't highlight it in IDE. + $error = 'Blank line found at end of control structure'; + if ( isset( $phpcsFile->fixer ) ) { + $fix = $phpcsFile->addFixableError( $error, $i, 'BlankLineBeforeEnd' ); + if ( true === $fix ) { + $phpcsFile->fixer->beginChangeset(); + + for ( $j = ( $lastContent + 1 ); $j < $scopeCloser; $j++ ) { + $phpcsFile->fixer->replaceToken( $j, '' ); + } + + $phpcsFile->fixer->addNewlineBefore( $scopeCloser ); + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->addError( $error, $i, 'BlankLineBeforeEnd' ); + } // end if + break; + } // end if + } // end for + } // end if + } // end if + + $trailingContent = $phpcsFile->findNext( T_WHITESPACE, ( $scopeCloser + 1 ), null, true ); + if ( T_ELSE === $this->tokens[ $trailingContent ]['code'] ) { + if ( T_IF === $this->tokens[ $stackPtr ]['code'] ) { + // IF with ELSE. + return; + } + } + + if ( T_COMMENT === $this->tokens[ $trailingContent ]['code'] ) { + if ( $this->tokens[ $trailingContent ]['line'] === $this->tokens[ $scopeCloser ]['line'] ) { + if ( '//end' === substr( $this->tokens[ $trailingContent ]['content'], 0, 5 ) ) { + // There is an end comment, so we have to get the next piece + // of content. + $trailingContent = $phpcsFile->findNext( T_WHITESPACE, ( $trailingContent + 1), null, true ); + } + } + } + + if ( T_BREAK === $this->tokens[ $trailingContent ]['code'] ) { + // If this BREAK is closing a CASE, we don't need the + // blank line after this control structure. + if ( isset( $this->tokens[ $trailingContent ]['scope_condition'] ) ) { + $condition = $this->tokens[ $trailingContent ]['scope_condition']; + if ( T_CASE === $this->tokens[ $condition ]['code'] || T_DEFAULT === $this->tokens[ $condition ]['code'] ) { + return; + } + } + } + + if ( T_CLOSE_TAG === $this->tokens[ $trailingContent ]['code'] ) { + // At the end of the script or embedded code. + return; + } + + if ( T_CLOSE_CURLY_BRACKET === $this->tokens[ $trailingContent ]['code'] ) { + // Another control structure's closing brace. + if ( isset( $this->tokens[ $trailingContent ]['scope_condition'] ) ) { + $owner = $this->tokens[ $trailingContent ]['scope_condition']; + if ( in_array( $this->tokens[ $owner ]['code'], array( T_FUNCTION, T_CLASS, T_INTERFACE, T_TRAIT ), true ) ) { + // The next content is the closing brace of a function, class, interface or trait + // so normal function/class rules apply and we can ignore it. + return; + } + } + + if ( true === $this->blank_line_after_check + && ( $this->tokens[ $scopeCloser ]['line'] + 1 ) !== $this->tokens[ $trailingContent ]['line'] + ) { + // TODO: Won't cover following case: "} echo 'OK';". + $error = 'Blank line found after control structure'; + if ( isset( $phpcsFile->fixer ) ) { + $fix = $phpcsFile->addFixableError( $error, $scopeCloser, 'BlankLineAfterEnd' ); + if ( true === $fix ) { + $phpcsFile->fixer->beginChangeset(); + + for ( $i = ( $scopeCloser + 1 ); $i < $trailingContent; $i++ ) { + $phpcsFile->fixer->replaceToken( $i, '' ); + } + + // TODO: Instead a separate error should be triggered when content comes right after closing brace. + $phpcsFile->fixer->addNewlineBefore( $trailingContent ); + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->addError( $error, $scopeCloser, 'BlankLineAfterEnd' ); + } + } + } // end if + + } // end process() + +} // End class. diff --git a/WordPress/Sniffs/WhiteSpace/OperatorSpacingSniff.php b/WordPress/Sniffs/WhiteSpace/OperatorSpacingSniff.php index be7b5aa4e1..18e3abe038 100644 --- a/WordPress/Sniffs/WhiteSpace/OperatorSpacingSniff.php +++ b/WordPress/Sniffs/WhiteSpace/OperatorSpacingSniff.php @@ -1,214 +1,214 @@ - * @author Marc McIntyre + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ /** - * Enforces WordPress array format + * Verify operator spacing, based upon Squiz code. + * + * "Always put spaces after commas, and on both sides of logical, comparison, string and assignment operators." + * + * @link https://make.wordpress.org/core/handbook/best-practices/coding-standards/php/#space-usage + * + * @package WPCS\WordPressCodingStandards + * + * @since 0.1.0 + * @since 0.3.0 This sniff now has the ability to fix the issues it flags. * - * @category PHP - * @package PHP_CodeSniffer - * @author Greg Sherwood - * @author Marc McIntyre + * Last synced with base class December 2008 at commit f01746fd1c89e98174b16c76efd325825eb58bf1. + * @link https://github.com/squizlabs/PHP_CodeSniffer/blob/master/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/OperatorSpacingSniff.php */ -class WordPress_Sniffs_WhiteSpace_OperatorSpacingSniff implements PHP_CodeSniffer_Sniff -{ - - /** - * A list of tokenizers this sniff supports. - * - * @var array - */ - public $supportedTokenizers = array( - 'PHP', - 'JS', - ); - - - /** - * Returns an array of tokens this test wants to listen for. - * - * @return array - */ - public function register() - { - $comparison = PHP_CodeSniffer_Tokens::$comparisonTokens; - $operators = PHP_CodeSniffer_Tokens::$operators; - $assignment = PHP_CodeSniffer_Tokens::$assignmentTokens; - - $tokens = array_unique(array_merge($comparison, $operators, $assignment)); - $tokens[] = T_BOOLEAN_NOT; - - return $tokens; - - }//end register() - - - /** - * Processes this sniff, when one of its tokens is encountered. - * - * @param PHP_CodeSniffer_File $phpcsFile The current file being checked. - * @param int $stackPtr The position of the current token in the - * stack passed in $tokens. - * - * @return void - */ - public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) - { - $tokens = $phpcsFile->getTokens(); - - if ($tokens[$stackPtr]['code'] === T_EQUAL) { - // Skip for '=&' case. - if (isset($tokens[($stackPtr + 1)]) === true && $tokens[($stackPtr + 1)]['code'] === T_BITWISE_AND) { - return; - } - - // Skip default values in function declarations. - if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) { - $bracket = end($tokens[$stackPtr]['nested_parenthesis']); - if (isset($tokens[$bracket]['parenthesis_owner']) === true) { - $function = $tokens[$bracket]['parenthesis_owner']; - if ($tokens[$function]['code'] === T_FUNCTION) { - return; - } - } - } - } - - if ($tokens[$stackPtr]['code'] === T_BITWISE_AND) { - // If its not a reference, then we expect one space either side of the - // bitwise operator. - if ($phpcsFile->isReference($stackPtr) === false) { - - }//end if - } else { - if ($tokens[$stackPtr]['code'] === T_MINUS) { - // Check minus spacing, but make sure we aren't just assigning - // a minus value or returning one. - $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); - if ($tokens[$prev]['code'] === T_RETURN) { - // Just returning a negative value; eg. return -1. - return; - } - - if (in_array($tokens[$prev]['code'], PHP_CodeSniffer_Tokens::$operators) === true) { - // Just trying to operate on a negative value; eg. ($var * -1). - return; - } - - if (in_array($tokens[$prev]['code'], PHP_CodeSniffer_Tokens::$comparisonTokens) === true) { - // Just trying to compare a negative value; eg. ($var === -1). - return; - } - - // A list of tokens that indicate that the token is not - // part of an arithmetic operation. - $invalidTokens = array( - T_COMMA, - T_OPEN_PARENTHESIS, - T_OPEN_SQUARE_BRACKET, - ); - - if (in_array($tokens[$prev]['code'], $invalidTokens) === true) { - // Just trying to use a negative value; eg. myFunction($var, -2). - return; - } - - $number = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); - if ($tokens[$number]['code'] === T_LNUMBER) { - $semi = $phpcsFile->findNext(T_WHITESPACE, ($number + 1), null, true); - if ($tokens[$semi]['code'] === T_SEMICOLON) { - if ($prev !== false && (in_array($tokens[$prev]['code'], PHP_CodeSniffer_Tokens::$assignmentTokens) === true)) { - // This is a negative assignment. - return; - } - } - } - }//end if - - $operator = $tokens[$stackPtr]['content']; - - if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE) { - $error = 'Expected 1 space before "%s"; 0 found'; - $data = array($operator); - if (isset($phpcsFile->fixer) === true) { - $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceBefore', $data); - if ($fix === true) { - $phpcsFile->fixer->beginChangeset(); - $phpcsFile->fixer->addContentBefore($stackPtr, ' '); - $phpcsFile->fixer->endChangeset(); - } - } else { - $phpcsFile->addError($error, $stackPtr, 'NoSpaceBefore', $data); - } - } else if (strlen($tokens[($stackPtr - 1)]['content']) !== 1 && $tokens[($stackPtr - 1)]['column'] !== 1) { - // Don't throw an error for assignments, because other standards allow - // multiple spaces there to align multiple assignments. - if (in_array($tokens[$stackPtr]['code'], PHP_CodeSniffer_Tokens::$assignmentTokens) === false) { - $found = strlen($tokens[($stackPtr - 1)]['content']); - $error = 'Expected 1 space before "%s"; %s found'; - $data = array( - $operator, - $found, - ); - if (isset($phpcsFile->fixer) === true) { - $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingBefore', $data); - if ($fix === true) { - $phpcsFile->fixer->beginChangeset(); - $phpcsFile->fixer->replaceToken(($stackPtr - 1), ' '); - $phpcsFile->fixer->endChangeset(); - } - } else { - $phpcsFile->addError($error, $stackPtr, 'SpacingBefore', $data); - } - } - }//end if - - if ($operator !== '-') { - if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) { - $error = 'Expected 1 space after "%s"; 0 found'; - $data = array($operator); - if (isset($phpcsFile->fixer) === true) { - $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoSpaceAfter', $data); - if ($fix === true) { - $phpcsFile->fixer->beginChangeset(); - $phpcsFile->fixer->addContent($stackPtr, ' '); - $phpcsFile->fixer->endChangeset(); - } - } else { - $phpcsFile->addError($error, $stackPtr, 'NoSpaceAfter', $data); - } - } else if (strlen($tokens[($stackPtr + 1)]['content']) !== 1) { - $found = strlen($tokens[($stackPtr + 1)]['content']); - $error = 'Expected 1 space after "%s"; %s found'; - $data = array( - $operator, - $found, - ); - if (isset($phpcsFile->fixer) === true) { - $fix = $phpcsFile->addFixableError($error, $stackPtr, 'SpacingAfter', $data); - if ($fix === true) { - $phpcsFile->fixer->beginChangeset(); - $phpcsFile->fixer->replaceToken(($stackPtr + 1), ' '); - $phpcsFile->fixer->endChangeset(); - } - } else { - $phpcsFile->addError($error, $stackPtr, 'SpacingAfter', $data); - } - }//end if - }//end if - }//end if - - }//end process() - - -}//end class - -?> +class WordPress_Sniffs_WhiteSpace_OperatorSpacingSniff implements PHP_CodeSniffer_Sniff { + + /** + * A list of tokenizers this sniff supports. + * + * @var array + */ + public $supportedTokenizers = array( + 'PHP', + 'JS', + ); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + $comparison = PHP_CodeSniffer_Tokens::$comparisonTokens; + $operators = PHP_CodeSniffer_Tokens::$operators; + $assignment = PHP_CodeSniffer_Tokens::$assignmentTokens; + + $tokens = array_unique( array_merge( $comparison, $operators, $assignment ) ); + $tokens[] = T_BOOLEAN_NOT; + + return $tokens; + + } + + /** + * Processes this sniff, when one of its tokens is encountered. + * + * @param PHP_CodeSniffer_File $phpcsFile The current file being checked. + * @param int $stackPtr The position of the current token in the + * stack passed in $tokens. + * + * @return void + */ + public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) { + $tokens = $phpcsFile->getTokens(); + + if ( T_EQUAL === $tokens[ $stackPtr ]['code'] ) { + // Skip for '=&' case. + if ( isset( $tokens[ ( $stackPtr + 1 ) ] ) && T_BITWISE_AND === $tokens[ ( $stackPtr + 1 ) ]['code'] ) { + return; + } + + // Skip default values in function declarations. + if ( isset( $tokens[ $stackPtr ]['nested_parenthesis'] ) ) { + $bracket = end( $tokens[ $stackPtr ]['nested_parenthesis'] ); + if ( isset( $tokens[ $bracket ]['parenthesis_owner'] ) ) { + $function = $tokens[ $bracket ]['parenthesis_owner']; + if ( T_FUNCTION === $tokens[ $function ]['code'] ) { + return; + } + } + } + } + + if ( T_BITWISE_AND === $tokens[ $stackPtr ]['code'] ) { + /* + // If it's not a reference, then we expect one space either side of the + // bitwise operator. + if ( false === $phpcsFile->isReference( $stackPtr ) ) { + // @todo Implement or remove ? + } + */ + return; + + } else { + if ( T_MINUS === $tokens[ $stackPtr ]['code'] ) { + // Check minus spacing, but make sure we aren't just assigning + // a minus value or returning one. + $prev = $phpcsFile->findPrevious( T_WHITESPACE, ( $stackPtr - 1 ), null, true ); + if ( T_RETURN === $tokens[ $prev ]['code'] ) { + // Just returning a negative value; eg. return -1. + return; + } + + if ( in_array( $tokens[ $prev ]['code'], PHP_CodeSniffer_Tokens::$operators, true ) ) { + // Just trying to operate on a negative value; eg. ($var * -1). + return; + } + + if ( in_array( $tokens[ $prev ]['code'], PHP_CodeSniffer_Tokens::$comparisonTokens, true ) ) { + // Just trying to compare a negative value; eg. ($var === -1). + return; + } + + // A list of tokens that indicate that the token is not + // part of an arithmetic operation. + $invalidTokens = array( + T_COMMA, + T_OPEN_PARENTHESIS, + T_OPEN_SQUARE_BRACKET, + ); + + if ( in_array( $tokens[ $prev ]['code'], $invalidTokens, true ) ) { + // Just trying to use a negative value; eg. myFunction($var, -2). + return; + } + + $number = $phpcsFile->findNext( T_WHITESPACE, ( $stackPtr + 1 ), null, true ); + if ( T_LNUMBER === $tokens[ $number ]['code'] ) { + $semi = $phpcsFile->findNext( T_WHITESPACE, ( $number + 1 ), null, true ); + if ( T_SEMICOLON === $tokens[ $semi ]['code'] ) { + if ( false !== $prev && in_array( $tokens[ $prev ]['code'], PHP_CodeSniffer_Tokens::$assignmentTokens, true ) ) { + // This is a negative assignment. + return; + } + } + } + } // end if + + $operator = $tokens[ $stackPtr ]['content']; + + if ( T_WHITESPACE !== $tokens[ ( $stackPtr - 1 ) ]['code'] ) { + $error = 'Expected 1 space before "%s"; 0 found'; + $data = array( $operator ); + if ( isset( $phpcsFile->fixer ) ) { + $fix = $phpcsFile->addFixableError( $error, $stackPtr, 'NoSpaceBefore', $data ); + if ( true === $fix ) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContentBefore( $stackPtr, ' ' ); + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->addError( $error, $stackPtr, 'NoSpaceBefore', $data ); + } + } elseif ( 1 !== strlen( $tokens[ ( $stackPtr - 1 ) ]['content'] ) && 1 !== $tokens[ ( $stackPtr - 1 ) ]['column'] ) { + // Don't throw an error for assignments, because other standards allow + // multiple spaces there to align multiple assignments. + if ( false === in_array( $tokens[ $stackPtr ]['code'], PHP_CodeSniffer_Tokens::$assignmentTokens, true ) ) { + $found = strlen( $tokens[ ( $stackPtr - 1 ) ]['content'] ); + $error = 'Expected 1 space before "%s"; %s found'; + $data = array( + $operator, + $found, + ); + if ( isset( $phpcsFile->fixer ) ) { + $fix = $phpcsFile->addFixableError( $error, $stackPtr, 'SpacingBefore', $data ); + if ( true === $fix ) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken( ( $stackPtr - 1 ), ' ' ); + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->addError( $error, $stackPtr, 'SpacingBefore', $data ); + } + } + } // end if + + if ( '-' !== $operator ) { + if ( T_WHITESPACE !== $tokens[ ( $stackPtr + 1 ) ]['code'] ) { + $error = 'Expected 1 space after "%s"; 0 found'; + $data = array( $operator ); + if ( isset( $phpcsFile->fixer ) ) { + $fix = $phpcsFile->addFixableError( $error, $stackPtr, 'NoSpaceAfter', $data ); + if ( true === $fix ) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->addContent( $stackPtr, ' ' ); + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->addError( $error, $stackPtr, 'NoSpaceAfter', $data ); + } + } elseif ( 1 !== strlen( $tokens[ ( $stackPtr + 1 ) ]['content'] ) ) { + $found = strlen( $tokens[ ( $stackPtr + 1 ) ]['content'] ); + $error = 'Expected 1 space after "%s"; %s found'; + $data = array( + $operator, + $found, + ); + if ( isset( $phpcsFile->fixer ) ) { + $fix = $phpcsFile->addFixableError( $error, $stackPtr, 'SpacingAfter', $data ); + if ( true === $fix ) { + $phpcsFile->fixer->beginChangeset(); + $phpcsFile->fixer->replaceToken( ( $stackPtr + 1 ), ' ' ); + $phpcsFile->fixer->endChangeset(); + } + } else { + $phpcsFile->addError( $error, $stackPtr, 'SpacingAfter', $data ); + } + } // end if + } // end if + } // end if + + } // end process() + +} // End class. diff --git a/WordPress/Sniffs/XSS/EscapeOutputSniff.php b/WordPress/Sniffs/XSS/EscapeOutputSniff.php index 6381134ee6..237a9291a8 100644 --- a/WordPress/Sniffs/XSS/EscapeOutputSniff.php +++ b/WordPress/Sniffs/XSS/EscapeOutputSniff.php @@ -1,24 +1,25 @@ + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ /** * Verifies that all outputted strings are escaped. * - * @category PHP - * @package PHP_CodeSniffer - * @author Weston Ruter - * @link http://codex.wordpress.org/Data_Validation Data Validation on WordPress Codex + * @link http://codex.wordpress.org/Data_Validation Data Validation on WordPress Codex + * + * @package WPCS\WordPressCodingStandards + * + * @since 2013-06-11 + * @since 0.4.0 This class now extends WordPress_Sniff. + * @since 0.5.0 The various function list properties which used to be contained in this class + * have been moved to the WordPress_Sniff parent class. */ -class WordPress_Sniffs_XSS_EscapeOutputSniff extends WordPress_Sniff -{ +class WordPress_Sniffs_XSS_EscapeOutputSniff extends WordPress_Sniff { /** * Custom list of functions which escape values for output. @@ -41,8 +42,9 @@ class WordPress_Sniffs_XSS_EscapeOutputSniff extends WordPress_Sniff /** * Custom list of functions which escape values for output. * - * @since 0.3.0 + * @since 0.3.0 * @deprecated 0.5.0 Use $customEscapingFunctions instead. + * @see WordPress_Sniffs_XSS_EscapeOutputSniff::$customEscapingFunctions * * @var string[] */ @@ -65,7 +67,7 @@ class WordPress_Sniffs_XSS_EscapeOutputSniff extends WordPress_Sniff * @var array */ public static $unsafePrintingFunctions = array( - '_e' => 'esc_html_e() or esc_attr_e()', + '_e' => 'esc_html_e() or esc_attr_e()', '_ex' => 'esc_html_ex() or esc_attr_ex()', ); @@ -76,13 +78,27 @@ class WordPress_Sniffs_XSS_EscapeOutputSniff extends WordPress_Sniff */ public static $addedCustomFunctions = false; + /** + * List of names of the tokens representing PHP magic constants. + * + * @var array + */ + private $magic_constant_tokens = array( + 'T_CLASS_C' => true, // __CLASS__ + 'T_FILE' => true, // __FILE__ + 'T_FUNC_C' => true, // __FUNCTION__ + 'T_LINE' => true, // __LINE__ + 'T_METHOD_C' => true, // __METHOD__ + 'T_NS_C' => true, // __NAMESPACE__ + 'T_TRAIT_C' => true, // __TRAIT__ + ); + /** * Returns an array of tokens this test wants to listen for. * * @return array */ - public function register() - { + public function register() { return array( T_ECHO, T_PRINT, @@ -90,8 +106,7 @@ public function register() T_STRING, ); - }//end register() - + } /** * Processes this test, when one of its tokens is encountered. @@ -102,16 +117,15 @@ public function register() * * @return int|void */ - public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) - { + public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) { // Merge any custom functions with the defaults, if we haven't already. if ( ! self::$addedCustomFunctions ) { - WordPress_Sniff::$escapingFunctions = array_merge( WordPress_Sniff::$escapingFunctions, array_flip( $this->customEscapingFunctions ) ); - WordPress_Sniff::$autoEscapedFunctions = array_merge( WordPress_Sniff::$autoEscapedFunctions, array_flip( $this->customAutoEscapedFunctions ) ); - WordPress_Sniff::$printingFunctions = array_merge( WordPress_Sniff::$printingFunctions, array_flip( $this->customPrintingFunctions ) ); + self::$escapingFunctions = array_merge( self::$escapingFunctions, array_flip( $this->customEscapingFunctions ) ); + self::$autoEscapedFunctions = array_merge( self::$autoEscapedFunctions, array_flip( $this->customAutoEscapedFunctions ) ); + self::$printingFunctions = array_merge( self::$printingFunctions, array_flip( $this->customPrintingFunctions ) ); if ( ! empty( $this->customSanitizingFunctions ) ) { - WordPress_Sniff::$escapingFunctions = array_merge( WordPress_Sniff::$escapingFunctions, array_flip( $this->customSanitizingFunctions ) ); + self::$escapingFunctions = array_merge( self::$escapingFunctions, array_flip( $this->customSanitizingFunctions ) ); $phpcsFile->addWarning( 'The customSanitizingFunctions property is deprecated in favor of customEscapingFunctions.', 0, 'DeprecatedCustomSanitizingFunctions' ); } @@ -119,31 +133,30 @@ public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) } $this->init( $phpcsFile ); - $tokens = $phpcsFile->getTokens(); - $function = $tokens[ $stackPtr ]['content']; + $function = $this->tokens[ $stackPtr ]['content']; // Find the opening parenthesis (if present; T_ECHO might not have it). - $open_paren = $phpcsFile->findNext( PHP_CodeSniffer_Tokens::$emptyTokens, $stackPtr + 1, null, true ); + $open_paren = $phpcsFile->findNext( PHP_CodeSniffer_Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true ); - // If function, not T_ECHO nor T_PRINT - if ( $tokens[$stackPtr]['code'] == T_STRING ) { + // If function, not T_ECHO nor T_PRINT. + if ( T_STRING === $this->tokens[ $stackPtr ]['code'] ) { // Skip if it is a function but is not of the printing functions. - if ( ! isset( self::$printingFunctions[ $tokens[ $stackPtr ]['content'] ] ) ) { + if ( ! isset( self::$printingFunctions[ $this->tokens[ $stackPtr ]['content'] ] ) ) { return; } - if ( isset( $tokens[ $open_paren ]['parenthesis_closer'] ) ) { - $end_of_statement = $tokens[ $open_paren ]['parenthesis_closer']; + if ( isset( $this->tokens[ $open_paren ]['parenthesis_closer'] ) ) { + $end_of_statement = $this->tokens[ $open_paren ]['parenthesis_closer']; } // These functions only need to have the first argument escaped. - if ( in_array( $function, array( 'trigger_error', 'user_error' ) ) ) { + if ( in_array( $function, array( 'trigger_error', 'user_error' ), true ) ) { $end_of_statement = $phpcsFile->findEndOfStatement( $open_paren + 1 ); } } - // Checking for the ignore comment, ex: //xss ok + // Checking for the ignore comment, ex: //xss ok. if ( $this->has_whitelist_comment( 'xss', $stackPtr ) ) { return; } @@ -163,17 +176,17 @@ public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) if ( ! isset( $end_of_statement ) ) { $end_of_statement = $phpcsFile->findNext( array( T_SEMICOLON, T_CLOSE_TAG ), $stackPtr ); - $last_token = $phpcsFile->findPrevious( PHP_CodeSniffer_Tokens::$emptyTokens, $end_of_statement - 1, null, true ); + $last_token = $phpcsFile->findPrevious( PHP_CodeSniffer_Tokens::$emptyTokens, ( $end_of_statement - 1 ), null, true ); // Check for the ternary operator. We only need to do this here if this // echo is lacking parenthesis. Otherwise it will be handled below. - if ( T_OPEN_PARENTHESIS !== $tokens[ $open_paren ]['code'] || T_CLOSE_PARENTHESIS !== $tokens[ $last_token ]['code'] ) { + if ( T_OPEN_PARENTHESIS !== $this->tokens[ $open_paren ]['code'] || T_CLOSE_PARENTHESIS !== $this->tokens[ $last_token ]['code'] ) { $ternary = $phpcsFile->findNext( T_INLINE_THEN, $stackPtr, $end_of_statement ); // If there is a ternary skip over the part before the ?. However, if // the ternary is within parentheses, it will be handled in the loop. - if ( $ternary && empty( $tokens[ $ternary ]['nested_parenthesis'] ) ) { + if ( $ternary && empty( $this->tokens[ $ternary ]['nested_parenthesis'] ) ) { $stackPtr = $ternary; } } @@ -184,34 +197,34 @@ public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) $in_cast = false; - // looping through echo'd components + // Looping through echo'd components. $watch = true; for ( $i = $stackPtr; $i < $end_of_statement; $i++ ) { // Ignore whitespaces and comments. - if ( in_array( $tokens[ $i ]['code'], array( T_WHITESPACE, T_COMMENT ) ) ) { + if ( in_array( $this->tokens[ $i ]['code'], PHP_CodeSniffer_Tokens::$emptyTokens, true ) ) { continue; } - if ( T_OPEN_PARENTHESIS === $tokens[ $i ]['code'] ) { + if ( T_OPEN_PARENTHESIS === $this->tokens[ $i ]['code'] ) { if ( $in_cast ) { // Skip to the end of a function call if it has been casted to a safe value. - $i = $tokens[ $i ]['parenthesis_closer']; + $i = $this->tokens[ $i ]['parenthesis_closer']; $in_cast = false; } else { // Skip over the condition part of a ternary (i.e., to after the ?). - $ternary = $phpcsFile->findNext( T_INLINE_THEN, $i, $tokens[ $i ]['parenthesis_closer'] ); + $ternary = $phpcsFile->findNext( T_INLINE_THEN, $i, $this->tokens[ $i ]['parenthesis_closer'] ); if ( $ternary ) { - $next_paren = $phpcsFile->findNext( T_OPEN_PARENTHESIS, $i + 1, $tokens[ $i ]['parenthesis_closer'] ); + $next_paren = $phpcsFile->findNext( T_OPEN_PARENTHESIS, ( $i + 1 ), $this->tokens[ $i ]['parenthesis_closer'] ); // We only do it if the ternary isn't within a subset of parentheses. - if ( ! $next_paren || $ternary > $tokens[ $next_paren ]['parenthesis_closer'] ) { + if ( ! $next_paren || $ternary > $this->tokens[ $next_paren ]['parenthesis_closer'] ) { $i = $ternary; } } @@ -221,52 +234,53 @@ public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) } // Handle arrays for those functions that accept them. - if ( $tokens[ $i ]['code'] === T_ARRAY ) { + if ( T_ARRAY === $this->tokens[ $i ]['code'] ) { $i++; // Skip the opening parenthesis. continue; } - if ( in_array( $tokens[ $i ]['code'], array( T_DOUBLE_ARROW, T_CLOSE_PARENTHESIS ) ) ) { + if ( in_array( $this->tokens[ $i ]['code'], array( T_DOUBLE_ARROW, T_CLOSE_PARENTHESIS ), true ) ) { continue; } // Handle magic constants for debug functions. - if ( in_array( $tokens[ $i ]['code'], array( T_METHOD_C, T_FUNC_C, T_FILE, T_CLASS_C ) ) ) { + if ( isset( $this->magic_constant_tokens[ $this->tokens[ $i ]['type'] ] ) ) { continue; } - // Wake up on concatenation characters, another part to check - if ( in_array( $tokens[$i]['code'], array( T_STRING_CONCAT ) ) ) { + // Wake up on concatenation characters, another part to check. + if ( in_array( $this->tokens[ $i ]['code'], array( T_STRING_CONCAT ), true ) ) { $watch = true; continue; } // Wake up after a ternary else (:). - if ( $ternary && in_array( $tokens[$i]['code'], array( T_INLINE_ELSE ) ) ) { + if ( $ternary && in_array( $this->tokens[ $i ]['code'], array( T_INLINE_ELSE ), true ) ) { $watch = true; continue; } // Wake up for commas. - if ( $tokens[ $i ]['code'] === T_COMMA ) { + if ( T_COMMA === $this->tokens[ $i ]['code'] ) { $in_cast = false; - $watch = true; + $watch = true; continue; } - if ( $watch === false ) + if ( false === $watch ) { continue; + } // Allow T_CONSTANT_ENCAPSED_STRING eg: echo 'Some String'; // Also T_LNUMBER, e.g.: echo 45; exit -1; and booleans. - if ( in_array( $tokens[$i]['code'], array( T_CONSTANT_ENCAPSED_STRING, T_LNUMBER, T_MINUS, T_TRUE, T_FALSE, T_NULL ) ) ) { + if ( in_array( $this->tokens[ $i ]['code'], array( T_CONSTANT_ENCAPSED_STRING, T_LNUMBER, T_MINUS, T_TRUE, T_FALSE, T_NULL ), true ) ) { continue; } $watch = false; - // Allow int/double/bool casted variables - if ( in_array( $tokens[$i]['code'], array( T_INT_CAST, T_DOUBLE_CAST, T_BOOL_CAST ) ) ) { + // Allow int/double/bool casted variables. + if ( in_array( $this->tokens[ $i ]['code'], array( T_INT_CAST, T_DOUBLE_CAST, T_BOOL_CAST ), true ) ) { $in_cast = true; continue; } @@ -274,12 +288,9 @@ public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) // Now check that next token is a function call. if ( T_STRING === $this->tokens[ $i ]['code'] ) { - $ptr = $i; - - $functionName = $this->tokens[ $i ]['content']; - - $function_opener = $this->phpcsFile->findNext( array( T_OPEN_PARENTHESIS ), $i + 1, null, null, null, true ); - + $ptr = $i; + $functionName = $this->tokens[ $i ]['content']; + $function_opener = $this->phpcsFile->findNext( array( T_OPEN_PARENTHESIS ), ( $i + 1 ), null, null, null, true ); $is_formatting_function = isset( self::$formattingFunctions[ $functionName ] ); if ( $function_opener ) { @@ -289,8 +300,8 @@ public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) // Get the first parameter (name of function being used on the array). $mapped_function = $this->phpcsFile->findNext( PHP_CodeSniffer_Tokens::$emptyTokens, - $function_opener + 1, - $tokens[ $function_opener ]['parenthesis_closer'], + ( $function_opener + 1 ), + $this->tokens[ $function_opener ]['parenthesis_closer'], true ); @@ -305,7 +316,7 @@ public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) // If this is a formatting function we just skip over the opening // parenthesis. Otherwise we skip all the way to the closing. if ( $is_formatting_function ) { - $i = $function_opener + 1; + $i = ( $function_opener + 1 ); $watch = true; } else { $i = $this->tokens[ $function_opener ]['parenthesis_closer']; @@ -325,7 +336,7 @@ public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) } else { $content = $this->tokens[ $i ]['content']; - $ptr = $i; + $ptr = $i; } $this->phpcsFile->addError( @@ -338,8 +349,6 @@ public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) return $end_of_statement; - }//end process() - -}//end class + } // end process() -?> +} // End class. diff --git a/WordPress/Tests/Arrays/ArrayAssignmentRestrictionsUnitTest.inc b/WordPress/Tests/Arrays/ArrayAssignmentRestrictionsUnitTest.inc index e592293211..7f5d00841e 100644 --- a/WordPress/Tests/Arrays/ArrayAssignmentRestrictionsUnitTest.inc +++ b/WordPress/Tests/Arrays/ArrayAssignmentRestrictionsUnitTest.inc @@ -1,7 +1,7 @@ 1 ); // Bad +$foo = array( 'bar' => 1 ); // Bad. -$foo['bar'] = 1; // Bad +$foo['bar'] = 1; // Bad. -$foo = 'test' . 'bar=1&taz=5&bar=2'; // Bad +$foo = 'test' . 'bar=1&taz=5&bar=2'; // Bad. diff --git a/WordPress/Tests/Arrays/ArrayAssignmentRestrictionsUnitTest.php b/WordPress/Tests/Arrays/ArrayAssignmentRestrictionsUnitTest.php index 259212372e..952516ac0f 100644 --- a/WordPress/Tests/Arrays/ArrayAssignmentRestrictionsUnitTest.php +++ b/WordPress/Tests/Arrays/ArrayAssignmentRestrictionsUnitTest.php @@ -1,63 +1,60 @@ + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ -class WordPress_Tests_Arrays_ArrayAssignmentRestrictionsUnitTest extends AbstractSniffUnitTest -{ +/** + * Unit test class for the ArrayAssignmentRestrictions sniff. + * + * @package WPCS\WordPressCodingStandards + * @since 0.3.0 + */ +class WordPress_Tests_Arrays_ArrayAssignmentRestrictionsUnitTest extends AbstractSniffUnitTest { + + /** + * Fill in the $groups property to test the abstract class. + */ protected function setUp() { parent::setUp(); - WordPress_Sniffs_Arrays_ArrayAssignmentRestrictionsSniff::$groups = array( + WordPress_AbstractArrayAssignmentRestrictionsSniff::$groups = array( 'posts_per_page' => array( - 'type' => 'error', + 'type' => 'error', 'message' => 'Found assignment value of %s to be %s', - 'keys' => array( + 'keys' => array( 'foo', 'bar', - ), ), - ); + ), + ); + } + + /** + * Returns the lines where errors should occur. + * + * @return array => + */ + public function getErrorList() { + return array( + 3 => 1, + 5 => 1, + 7 => 2, + ); + + } + + /** + * Returns the lines where warnings should occur. + * + * @return array => + */ + public function getWarningList() { + return array(); + } - /** - * Returns the lines where errors should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of errors that should occur on that line. - * - * @return array(int => int) - */ - public function getErrorList() - { - return array( - 3 => 1, - 5 => 1, - 7 => 2, - ); - - }//end getErrorList() - - - /** - * Returns the lines where warnings should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) - */ - public function getWarningList() - { - return array( - ); - - }//end getWarningList() - - -}//end class +} // End class. diff --git a/WordPress/Tests/Arrays/ArrayDeclarationUnitTest.inc b/WordPress/Tests/Arrays/ArrayDeclarationUnitTest.inc index b8357583f3..12831f7841 100644 --- a/WordPress/Tests/Arrays/ArrayDeclarationUnitTest.inc +++ b/WordPress/Tests/Arrays/ArrayDeclarationUnitTest.inc @@ -1,48 +1,48 @@ 'food'), // Bad, no spaces after opening and befoer closing paranthesis + array('post_type' => 'food'), // Bad, no spaces after opening and before closing paranthesis. // ... array( 'post_status' => 'private', - 'orderby' => 'title' // Bad, no comma at the ending + 'orderby' => 'title' // Bad, no comma at the ending. ) ); $query = new WP_Query( $query_vars ); $query_vars = array_merge( - array( 'post_type' => 'food' ), // Good + array( 'post_type' => 'food' ), // Good. // ... array( 'post_status' => 'private', - 'orderby' => 'title', // Good + 'orderby' => 'title', // Good. ), array( - 'closure' => function () { // Good, Closures allowed + 'closure' => function () { // Good, closures allowed. return array(); }, ), - bar( // Good, Functions allowed + bar( // Good, functions allowed. 1, 2 ) ); $query = new WP_Query( $query_vars ); -$defaults = array( 'type'=>'post' ); // Bad, no spaces before and after double arrow +$defaults = array( 'type'=>'post' ); // Bad, no spaces before and after double arrow. wp_parse_args( $args, $defaults ); class Foo { function to_markdown( $params = array() ) { - // Parse sections + // Parse sections. $section_formatters = array( 'Description' => function ( $body ) use ( $params ) { if ( isset( $params['travis_ci_url'] ) ) { @@ -69,15 +69,15 @@ class Foo { } $primary_order = array( - 'n', // null - 'b', // boolean - 'i', // integer - 'f', // float - 's', // string - 'a', // array - 'o', // object - 'r', // resource - 'p', // SPL_Types object + 'n', // Null. + 'b', // Boolean. + 'i', // Integer. + 'f', // Float. + 's', // String. + 'a', // Array. + 'o', // Object. + 'r', // Resource. + 'p', // SPL_Types object. ); $var = array( @@ -89,7 +89,7 @@ $var = array( ', ); -// This should all be good: +// This should all be good. $section_args = array( 'title' => sprintf( __( 'Sidebar: %s', 'widget-customizer' ), @@ -125,67 +125,67 @@ $actions = array( ); $custom_fields = array( - 'videoembed', // Press75 Simple Video Embedder - '_videoembed_manual', // Press75 Simple Video Embedder - '_videoembed', // Press75 Simple Video Embedder - '_premise_settings', // Premise + 'videoembed', // Press75 Simple Video Embedder. + '_videoembed_manual', // Press75 Simple Video Embedder. + '_videoembed', // Press75 Simple Video Embedder. + '_premise_settings', // Premise. ); $item_block_comment = array( 'item', - /* Some comment */ + /* Some comment. */ ); $item_multiple_line_block_comment = array( 'item', /* Some comment - over multiple lines */ + over multiple lines. */ ); $block_comment = array( - /* Just a comment */ + /* Just a comment. */ ); $comment = array( - // Just a single comment + // Just a single comment. ); $multidimensional_comments = array( 'item_block_comment' => array( 'item', - /* comment */ + /* Comment. */ ), 'block_comment' => array( - /* comment */ + /* Comment. */ ), 'item_comment' => array( 'item', - // comment + // Comment. ), 'comment' => array( - // comment + // Comment. ), - // comment + // Comment. array( 'item', - /* comment */ + /* Comment. */ ), array( - /* comment */ + /* Comment. */ ), array( 'item', - // comment + // Comment. ), array( - // comment + // Comment. ), - // comment + // Comment. ); $q = new WP_Query( array( 'meta_query' => array( - 'relation' => 'and', // OK + 'relation' => 'and', // Ok. array( 'key' => 'asdsa', 'value' => 'asds', @@ -198,7 +198,7 @@ array( /** * Doc comment. */ -// 'core' +// 'core'. ); // Multiple values in an array on a single line is allowed. diff --git a/WordPress/Tests/Arrays/ArrayDeclarationUnitTest.inc.fixed b/WordPress/Tests/Arrays/ArrayDeclarationUnitTest.inc.fixed index 23b2a7d8e7..cbe7ae78a6 100644 --- a/WordPress/Tests/Arrays/ArrayDeclarationUnitTest.inc.fixed +++ b/WordPress/Tests/Arrays/ArrayDeclarationUnitTest.inc.fixed @@ -1,48 +1,48 @@ 'food' ), // Bad, no spaces after opening and befoer closing paranthesis + array( 'post_type' => 'food' ), // Bad, no spaces after opening and before closing paranthesis. // ... array( 'post_status' => 'private', - 'orderby' => 'title',// Bad, no comma at the ending + 'orderby' => 'title',// Bad, no comma at the ending. ) ); $query = new WP_Query( $query_vars ); $query_vars = array_merge( - array( 'post_type' => 'food' ), // Good + array( 'post_type' => 'food' ), // Good. // ... array( 'post_status' => 'private', - 'orderby' => 'title', // Good + 'orderby' => 'title', // Good. ), array( - 'closure' => function () { // Good, Closures allowed + 'closure' => function () { // Good, closures allowed. return array(); }, ), - bar( // Good, Functions allowed + bar( // Good, functions allowed. 1, 2 ) ); $query = new WP_Query( $query_vars ); -$defaults = array( 'type' => 'post' ); // Bad, no spaces before and after double arrow +$defaults = array( 'type' => 'post' ); // Bad, no spaces before and after double arrow. wp_parse_args( $args, $defaults ); class Foo { function to_markdown( $params = array() ) { - // Parse sections + // Parse sections. $section_formatters = array( 'Description' => function ( $body ) use ( $params ) { if ( isset( $params['travis_ci_url'] ) ) { @@ -69,15 +69,15 @@ class Foo { } $primary_order = array( - 'n', // null - 'b', // boolean - 'i', // integer - 'f', // float - 's', // string - 'a', // array - 'o', // object - 'r', // resource - 'p', // SPL_Types object + 'n', // Null. + 'b', // Boolean. + 'i', // Integer. + 'f', // Float. + 's', // String. + 'a', // Array. + 'o', // Object. + 'r', // Resource. + 'p', // SPL_Types object. ); $var = array( @@ -89,7 +89,7 @@ $var = array( ', ); -// This should all be good: +// This should all be good. $section_args = array( 'title' => sprintf( __( 'Sidebar: %s', 'widget-customizer' ), @@ -125,67 +125,67 @@ $actions = array( ); $custom_fields = array( - 'videoembed', // Press75 Simple Video Embedder - '_videoembed_manual', // Press75 Simple Video Embedder - '_videoembed', // Press75 Simple Video Embedder - '_premise_settings', // Premise + 'videoembed', // Press75 Simple Video Embedder. + '_videoembed_manual', // Press75 Simple Video Embedder. + '_videoembed', // Press75 Simple Video Embedder. + '_premise_settings', // Premise. ); $item_block_comment = array( 'item', - /* Some comment */ + /* Some comment. */ ); $item_multiple_line_block_comment = array( 'item', /* Some comment - over multiple lines */ + over multiple lines. */ ); $block_comment = array( - /* Just a comment */ + /* Just a comment. */ ); $comment = array( - // Just a single comment + // Just a single comment. ); $multidimensional_comments = array( 'item_block_comment' => array( 'item', - /* comment */ + /* Comment. */ ), 'block_comment' => array( - /* comment */ + /* Comment. */ ), 'item_comment' => array( 'item', - // comment + // Comment. ), 'comment' => array( - // comment + // Comment. ), - // comment + // Comment. array( 'item', - /* comment */ + /* Comment. */ ), array( - /* comment */ + /* Comment. */ ), array( 'item', - // comment + // Comment. ), array( - // comment + // Comment. ), - // comment + // Comment. ); $q = new WP_Query( array( 'meta_query' => array( - 'relation' => 'and', // OK + 'relation' => 'and', // Ok. array( 'key' => 'asdsa', 'value' => 'asds', @@ -198,7 +198,7 @@ array( /** * Doc comment. */ -// 'core' +// 'core'. ); // Multiple values in an array on a single line is allowed. diff --git a/WordPress/Tests/Arrays/ArrayDeclarationUnitTest.php b/WordPress/Tests/Arrays/ArrayDeclarationUnitTest.php index 3d5a98363c..c206bab99e 100644 --- a/WordPress/Tests/Arrays/ArrayDeclarationUnitTest.php +++ b/WordPress/Tests/Arrays/ArrayDeclarationUnitTest.php @@ -1,76 +1,46 @@ - * @author Greg Sherwood - * @author Marc McIntyre - * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence - * @link http://pear.php.net/package/PHP_CodeSniffer + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ /** * Unit test class for the ArrayDeclaration sniff. * - * A sniff unit test checks a .inc file for expected violations of a single - * coding standard. Expected errors and warnings are stored in this class. - * - * @category PHP - * @package PHP_CodeSniffer - * @author Akeda Bagus - * @author Greg Sherwood - * @author Marc McIntyre - * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence - * @version Release: @package_version@ - * @link http://pear.php.net/package/PHP_CodeSniffer + * @package WPCS\WordPressCodingStandards + * @since 2013-06-11 */ -class WordPress_Tests_Arrays_ArrayDeclarationUnitTest extends AbstractSniffUnitTest -{ - - - /** - * Returns the lines where errors should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of errors that should occur on that line. - * - * @return array(int => int) - */ - public function getErrorList() - { - return array( - 3 => 1, - 7 => 1, - 9 => 1, - 12 => 2, - 16 => 1, - 40 => 2, - 208 => 2, - ); - - }//end getErrorList() - - - /** - * Returns the lines where warnings should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) - */ - public function getWarningList() - { - return array( - ); - - }//end getWarningList() - - -}//end class - -?> +class WordPress_Tests_Arrays_ArrayDeclarationUnitTest extends AbstractSniffUnitTest { + + /** + * Returns the lines where errors should occur. + * + * @return array => + */ + public function getErrorList() { + return array( + 3 => 1, + 7 => 1, + 9 => 1, + 12 => 2, + 16 => 1, + 40 => 2, + 208 => 2, + ); + + } + + /** + * Returns the lines where warnings should occur. + * + * @return array => + */ + public function getWarningList() { + return array(); + + } + +} // End class. diff --git a/WordPress/Tests/Arrays/ArrayKeySpacingRestrictionsUnitTest.inc b/WordPress/Tests/Arrays/ArrayKeySpacingRestrictionsUnitTest.inc index a149f21b77..ab7fae7162 100644 --- a/WordPress/Tests/Arrays/ArrayKeySpacingRestrictionsUnitTest.inc +++ b/WordPress/Tests/Arrays/ArrayKeySpacingRestrictionsUnitTest.inc @@ -1,31 +1,31 @@ + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ -class WordPress_Tests_Arrays_ArrayKeySpacingRestrictionsUnitTest extends AbstractSniffUnitTest -{ + +/** + * Unit test class for the ArrayKeySpacingRestrictions sniff. + * + * @package WPCS\WordPressCodingStandards + * @since 0.3.0 + */ +class WordPress_Tests_Arrays_ArrayKeySpacingRestrictionsUnitTest extends AbstractSniffUnitTest { /** * Returns the lines where errors should occur. * - * The key of the array should represent the line number and the value - * should represent the number of errors that should occur on that line. - * - * @return array(int => int) + * @return array => */ - public function getErrorList() - { + public function getErrorList() { return array( 4 => 1, 5 => 1, @@ -35,21 +36,16 @@ public function getErrorList() 29 => 1, 31 => 1, ); - }//end getErrorList() - + } /** * Returns the lines where warnings should occur. * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) + * @return array => */ - public function getWarningList() - { + public function getWarningList() { return array(); - }//end getWarningList() + } -}//end class +} // End class. diff --git a/WordPress/Tests/CSRF/NonceVerificationUnitTest.inc b/WordPress/Tests/CSRF/NonceVerificationUnitTest.inc index e6b612f5c8..c6eb4e9c9c 100644 --- a/WordPress/Tests/CSRF/NonceVerificationUnitTest.inc +++ b/WordPress/Tests/CSRF/NonceVerificationUnitTest.inc @@ -2,11 +2,11 @@ // Bad, needs nonce check. function bar() { - if ( ! isset( $_POST['test'] ) ) { // Bad + if ( ! isset( $_POST['test'] ) ) { // Bad. return; } - do_something( $_POST['test'] ); // Bad + do_something( $_POST['test'] ); // Bad. } // Good, has an nonce check. @@ -28,7 +28,7 @@ function foo() { // Doing other things with the request params before the nonce check is prohibited. function process() { - do_something( $_POST['foo'] ); // Bad + do_something( $_POST['foo'] ); // Bad. if ( ! isset( $_POST['test'] ) || ! wp_verify_nonce( 'some_action' ) ) { exit; @@ -41,11 +41,11 @@ class Some_Class { // Bad, needs nonce check. function bar() { - if ( ! isset( $_POST['test'] ) ) { // Bad + if ( ! isset( $_POST['test'] ) ) { // Bad. return; } - do_something( $_POST['test'] ); // Bad + do_something( $_POST['test'] ); // Bad. } // Good, has an nonce check. @@ -66,7 +66,7 @@ class Some_Class { // Doing other things with the request params before the nonce check is prohibited. function process() { - do_something( $_POST['foo'] ); // Bad + do_something( $_POST['foo'] ); // Bad. if ( ! isset( $_POST['test'] ) || ! wp_verify_nonce( 'some_action' ) ) { exit; @@ -78,20 +78,20 @@ class Some_Class { // Assignments are allowed. function foo_2() { - $_POST = array( 'a' => 'b' ); // OK - $_POST['test'] = somethin(); // OK - $_POST['settings'][ $setting ] = 'bb'; // OK + $_POST = array( 'a' => 'b' ); // OK. + $_POST['test'] = somethin(); // OK. + $_POST['settings'][ $setting ] = 'bb'; // OK. } // Particular cases can be whitelisted with a comment. function foo_3() { - bar( $_POST['var'] ); // WPCS: CSRF OK - bar( $_POST['var'] ); // Bad + bar( $_POST['var'] ); // WPCS: CSRF OK. + bar( $_POST['var'] ); // Bad. } // We need to account for when there are multiple vars in a single isset(). function foo_4() { - if ( ! isset( $_POST['foo'], $_POST['bar'], $_POST['_wpnonce'] ) ) { // OK + if ( ! isset( $_POST['foo'], $_POST['bar'], $_POST['_wpnonce'] ) ) { // OK. return; } @@ -101,8 +101,8 @@ function foo_4() { // Sanitization before the nonce check is permitted. function sanitization_allowed() { - $foo = (int) $_POST['foo']; // OK - $bar = sanitize_key( $_POST['bar'] ); // OK + $foo = (int) $_POST['foo']; // OK. + $bar = sanitize_key( $_POST['bar'] ); // OK. check_ajax_referer( "something-{$foo}-{$bar}" ); } @@ -110,8 +110,8 @@ function sanitization_allowed() { // The value must only be sanitized though. function foo_5() { - do_something( (int) $_POST['foo'] ); // Bad - do_something( sanitize_key( $_POST['bar'] ) ); // Bad + do_something( (int) $_POST['foo'] ); // Bad. + do_something( sanitize_key( $_POST['bar'] ) ); // Bad. check_ajax_referer( 'something' ); } diff --git a/WordPress/Tests/CSRF/NonceVerificationUnitTest.php b/WordPress/Tests/CSRF/NonceVerificationUnitTest.php index 75642783f1..66979da9f9 100644 --- a/WordPress/Tests/CSRF/NonceVerificationUnitTest.php +++ b/WordPress/Tests/CSRF/NonceVerificationUnitTest.php @@ -1,25 +1,24 @@ - * @link http://pear.php.net/package/PHP_CodeSniffer + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ +/** + * Unit test class for the NonceVerification sniff. + * + * @package WPCS\WordPressCodingStandards + * @since 0.5.0 + */ class WordPress_Tests_CSRF_NonceVerificationUnitTest extends AbstractSniffUnitTest { /** * Returns the lines where errors should occur. * - * The key of the array should represent the line number and the value - * should represent the number of errors that should occur on that line. - * - * @return array(int => int) + * @return array => */ public function getErrorList() { @@ -39,13 +38,11 @@ public function getErrorList() { /** * Returns the lines where warnings should occur. * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) + * @return array => */ public function getWarningList() { return array(); + } -} // end class +} // End class. diff --git a/WordPress/Tests/Classes/ClassOpeningStatementUnitTest.inc b/WordPress/Tests/Classes/ClassOpeningStatementUnitTest.inc new file mode 100644 index 0000000000..1356e5b146 --- /dev/null +++ b/WordPress/Tests/Classes/ClassOpeningStatementUnitTest.inc @@ -0,0 +1,81 @@ + => + */ + public function getErrorList() { + + return array( + 19 => 2, + 23 => 1, + 28 => 2, + 34 => 1, + 34 => 1, + 38 => 1, + 41 => 1, + 44 => 1, + 47 => 1, + 70 => 1, + 79 => 1, + ); + + } + + /** + * Returns the lines where warnings should occur. + * + * @return array => + */ + public function getWarningList() { + return array( + 51 => 1, + ); + + } + +} // End class. diff --git a/WordPress/Tests/Classes/ValidClassNameUnitTest.inc b/WordPress/Tests/Classes/ValidClassNameUnitTest.inc index 485ad2705f..f4914ededd 100644 --- a/WordPress/Tests/Classes/ValidClassNameUnitTest.inc +++ b/WordPress/Tests/Classes/ValidClassNameUnitTest.inc @@ -1,7 +1,7 @@ - * @author Greg Sherwood - * @author Marc McIntyre - * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence - * @link http://pear.php.net/package/PHP_CodeSniffer + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ /** * Unit test class for the ValidClassName sniff. * - * A sniff unit test checks a .inc file for expected violations of a single - * coding standard. Expected errors and warnings are stored in this class. - * - * @category PHP - * @package PHP_CodeSniffer - * @author Akeda Bagus - * @author Greg Sherwood - * @author Marc McIntyre - * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence - * @version Release: @package_version@ - * @link http://pear.php.net/package/PHP_CodeSniffer + * @package WPCS\WordPressCodingStandards + * @since 2013-06-11 */ -class WordPress_Tests_Classes_ValidClassNameUnitTest extends AbstractSniffUnitTest -{ - - - /** - * Returns the lines where errors should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of errors that should occur on that line. - * - * @return array(int => int) - */ - public function getErrorList() - { - return array( - 7 => 1, - ); - - }//end getErrorList() - - - /** - * Returns the lines where warnings should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) - */ - public function getWarningList() - { - return array(); - - }//end getWarningList() - - -}//end class - -?> +class WordPress_Tests_Classes_ValidClassNameUnitTest extends AbstractSniffUnitTest { + + /** + * Returns the lines where errors should occur. + * + * @return array => + */ + public function getErrorList() { + return array( + 7 => 1, + ); + + } + + /** + * Returns the lines where warnings should occur. + * + * @return array => + */ + public function getWarningList() { + return array(); + + } + +} // End class. diff --git a/WordPress/Tests/DB/RestrictedClassesUnitTest.1.inc b/WordPress/Tests/DB/RestrictedClassesUnitTest.1.inc new file mode 100644 index 0000000000..594c0ae8b7 --- /dev/null +++ b/WordPress/Tests/DB/RestrictedClassesUnitTest.1.inc @@ -0,0 +1,41 @@ +exec(); +PDO::getAvailableDrivers(); + +$db7 = new PDOStatement; +$db8 = new \PDOStatement(); + diff --git a/WordPress/Tests/DB/RestrictedClassesUnitTest.2.inc b/WordPress/Tests/DB/RestrictedClassesUnitTest.2.inc new file mode 100644 index 0000000000..9536046e7a --- /dev/null +++ b/WordPress/Tests/DB/RestrictedClassesUnitTest.2.inc @@ -0,0 +1,47 @@ + resolves to \My\PDO. +} + +class DBextendes implements \PDO { // Bad -> fully qualified as \PDO. +} + +$db0 = new \DBlayer; // Ok - fully qualified as \DBlayer. +$db1 = new DBlayer; // Bad - resolves to \My\DBlayer. +$db2 = new DBlayer(); // Bad - resolves to \My\DBlayer. + +echo DBlayer::VERSION; // Bad - resolves to \My\DBlayer. +echo DBlayer::$property; // Bad - resolves to \My\DBlayer. +echo DBlayer::connect(); // Bad - resolves to \My\DBlayer. + +$db3 = new Yours\DBlayer; // Ok - resolves to \My\Yours\DBlayer. + +echo Yours\DBlayer::VERSION; // Ok - resolves to \My\Yours\DBlayer. +echo Yours\DBlayer::$property; // Ok - resolves to \My\Yours\DBlayer. +echo Yours\DBlayer::connect(); // Ok - resolves to \My\Yours\DBlayer. + +$db4 = new \My\DBlayer; // Bad - fully qualified as \My\DBlayer. + +echo \My\DBlayer::VERSION; // Bad - fully qualified as \My\DBlayer. +echo \My\DBlayer::$property; // Bad - fully qualified as \My\DBlayer. +echo \My\DBlayer::connect(); // Bad - fully qualified as \My\DBlayer. + +echo namespace\DBlayer::VERSION; // Bad - resolves to \My\DBlayer. +echo namespace\DBlayer::$property; // Bad - resolves to \My\DBlayer. +echo namespace\DBlayer::connect(); // Bad - resolves to \My\DBlayer. diff --git a/WordPress/Tests/DB/RestrictedClassesUnitTest.3.inc b/WordPress/Tests/DB/RestrictedClassesUnitTest.3.inc new file mode 100644 index 0000000000..3100d1c2f7 --- /dev/null +++ b/WordPress/Tests/DB/RestrictedClassesUnitTest.3.inc @@ -0,0 +1,92 @@ + resolves to \My\PDO. + } + + class DBextendes implements \PDO { // Bad -> fully qualified as \PDO. + } + + $db0 = new \DBlayer; // Ok - fully qualified as \DBlayer. + $db1 = new DBlayer; // Bad - resolves to \My\DBlayer. + $db2 = new DBlayer(); // Bad - resolves to \My\DBlayer. + + echo DBlayer::VERSION; // Bad - resolves to \My\DBlayer. + echo DBlayer::$property; // Bad - resolves to \My\DBlayer. + echo DBlayer::connect(); // Bad - resolves to \My\DBlayer. + + $db3 = new Yours\DBlayer; // Ok - resolves to \My\Yours\DBlayer. + + echo Yours\DBlayer::VERSION; // Ok - resolves to \My\Yours\DBlayer. + echo Yours\DBlayer::$property; // Ok - resolves to \My\Yours\DBlayer. + echo Yours\DBlayer::connect(); // Ok - resolves to \My\Yours\DBlayer. + + $db4 = new \My\DBlayer; // Bad - fully qualified as \My\DBlayer. + + echo \My\DBlayer::VERSION; // Bad - fully qualified as \My\DBlayer. + echo \My\DBlayer::$property; // Bad - fully qualified as \My\DBlayer. + echo \My\DBlayer::connect(); // Bad - fully qualified as \My\DBlayer. + + echo namespace\DBlayer::VERSION; // Bad - resolves to \My\DBlayer. + echo namespace\DBlayer::$property; // Bad - resolves to \My\DBlayer. + echo namespace\DBlayer::connect(); // Bad - resolves to \My\DBlayer. + +} + +// Now we're outside the namespace, so things should work differently. +$db0 = new \DBlayer; // Ok. +$db1 = new DBlayer; // Ok. +$db2 = new DBlayer(); // Ok. + +echo DBlayer::VERSION; // Ok. +echo DBlayer::$property; // Ok. +echo DBlayer::connect(); // Ok. + +$db3 = new Yours\DBlayer; // Ok - resolves to \Yours\DBlayer. + +echo Yours\DBlayer::VERSION; // Ok - resolves to \Yours\DBlayer. +echo Yours\DBlayer::$property; // Ok - resolves to \Yours\DBlayer. +echo Yours\DBlayer::connect(); // Ok - resolves to \Yours\DBlayer. + +$db4 = new \My\DBlayer; // Bad - fully qualified as \My\DBlayer. + +echo \My\DBlayer::VERSION; // Bad - fully qualified as \My\DBlayer. +echo \My\DBlayer::$property; // Bad - fully qualified as \My\DBlayer. +echo \My\DBlayer::connect(); // Bad - fully qualified as \My\DBlayer. + +echo namespace\DBlayer::VERSION; // Ok. +echo namespace\DBlayer::$property; // Ok. +echo namespace\DBlayer::connect(); // Ok. + + +// Testing second namespace within one file. +namespace AdoDb { + + class Test {} + + class Tester {} + + class TestAgain extends Test {} // Bad. + + class TestYetAgain extends Tester {} // Bad. + + $db5 = new Test; // Bad. + $db6 = new Tester(); // Bad. +} + +$db7 = new Test; // Ok. diff --git a/WordPress/Tests/DB/RestrictedClassesUnitTest.php b/WordPress/Tests/DB/RestrictedClassesUnitTest.php new file mode 100644 index 0000000000..c174c84fc4 --- /dev/null +++ b/WordPress/Tests/DB/RestrictedClassesUnitTest.php @@ -0,0 +1,141 @@ + array( + 'type' => 'error', + 'message' => 'Detected usage of %s.', + 'classes' => array( + '\My\DBlayer', + 'AdoDb\Test*', + ), + ), + ); + } + + /** + * Skip this test on PHP 5.2 as otherwise testing the namespace resolving would fail. + * + * @return bool Whether to skip this test. + */ + protected function shouldSkipTest() { + return version_compare( PHP_VERSION, '5.3.0', '<' ); + } + + /** + * Returns the lines where errors should occur. + * + * @param string $testFile The name of the file being tested. + * @return array => + */ + public function getErrorList( $testFile = '' ) { + switch ( $testFile ) { + case 'RestrictedClassesUnitTest.1.inc': + return array( + 17 => 1, + 18 => 1, + 19 => 1, + 20 => 1, + 22 => 1, + 23 => 1, + 24 => 1, + 25 => 1, + 26 => 1, + 27 => 1, + 29 => 1, + 30 => 1, + 32 => 1, + 33 => 1, + 35 => 1, + 36 => 1, + 37 => 1, + 39 => 1, + 40 => 1, + ); + + case 'RestrictedClassesUnitTest.2.inc': + return array( + 16 => 1, + 22 => 1, + 26 => 1, + 27 => 1, + 29 => 1, + 30 => 1, + 31 => 1, + 39 => 1, + 41 => 1, + 42 => 1, + 43 => 1, + 45 => 1, + 46 => 1, + 47 => 1, + ); + + case 'RestrictedClassesUnitTest.3.inc': + return array( + 16 => 1, + 22 => 1, + 26 => 1, + 27 => 1, + 29 => 1, + 30 => 1, + 31 => 1, + 39 => 1, + 41 => 1, + 42 => 1, + 43 => 1, + 45 => 1, + 46 => 1, + 47 => 1, + 66 => 1, + 68 => 1, + 69 => 1, + 70 => 1, + 84 => 1, + 86 => 1, + 88 => 1, + 89 => 1, + ); + + default: + return array(); + + } + + } // end getErrorList() + + /** + * Returns the lines where warnings should occur. + * + * @return array => + */ + public function getWarningList() { + return array(); + + } + +} // End class. diff --git a/WordPress/Tests/DB/RestrictedFunctionsUnitTest.inc b/WordPress/Tests/DB/RestrictedFunctionsUnitTest.inc new file mode 100644 index 0000000000..ab973dcf17 --- /dev/null +++ b/WordPress/Tests/DB/RestrictedFunctionsUnitTest.inc @@ -0,0 +1,90 @@ +mysql_info(); // Ok. +$y = Bar::mysql_info(); // Ok. +prefix_mysql_info(); // Ok. + + +/** + * All the below should give an error. + */ + +// MYSQL Extension. +mysql_affected_rows(); +mysql_connect(); +mysql_close(); +mysql_fetch_row(); +mysql_info(); +mysql_numrows(); +mysql_pconnect(); +mysql_query(); +mysql_result(); + +// MYSQLI Extension. +mysqli_client_encoding(); +mysqli_connect(); +mysqli_escape_string(); +mysqli_execute(); +mysqli_fetch(); +mysqli_get_metadata(); +mysqli_init(); +mysqli_options(); +mysqli_real_connect(); + +// MYSQLND_MS Extension. +mysqlnd_ms_fabric_select_global(); +mysqlnd_ms_get_stats(); +mysqlnd_ms_match_wild(); +mysqlnd_ms_xa_begin(); +mysqlnd_ms_xa_rollback(); + +// MYSQLND_QC Extension. +mysqlnd_qc_clear_cache(); +mysqlnd_qc_get_cache_info(); +mysqlnd_qc_get_query_trace_log(); +mysqlnd_qc_set_cache_condition(); + +// MYSQLND_UH Extension. +mysqlnd_uh_convert_to_mysqlnd(); + +// MYSQLND_MEMCACHE Extension. +mysqlnd_memcache_set(); + +// MAXDB Extension. +maxdb_affected_rows(); +maxdb_close(); +maxdb_connect(); +maxdb_errno(); +maxdb_escape_string(); +maxdb_fetch_assoc(); +maxdb_init(); +maxdb_num_fields(); +maxdb_prepare(); +maxdb_real_query(); +maxdb_stat(); + + +/** + * And these shouldn't give an error. + */ + +// WP Native function which was named a bit unfortunately. +mysql_to_rfc3339(); // Ok. + +// Other WP Native functions which shouldn't give a problem anyway. +mysql2date(); // Ok. +wp_check_mysql_version(); // Ok. +wp_check_php_mysql_version(); // Ok. +WP_Date_Query::build_mysql_datetime(); // Ok. diff --git a/WordPress/Tests/DB/RestrictedFunctionsUnitTest.php b/WordPress/Tests/DB/RestrictedFunctionsUnitTest.php new file mode 100644 index 0000000000..335e2bdce2 --- /dev/null +++ b/WordPress/Tests/DB/RestrictedFunctionsUnitTest.php @@ -0,0 +1,85 @@ + => + */ + public function getErrorList() { + return array( + 25 => 1, + 26 => 1, + 27 => 1, + 28 => 1, + 29 => 1, + 30 => 1, + 31 => 1, + 32 => 1, + 33 => 1, + + 36 => 1, + 37 => 1, + 38 => 1, + 39 => 1, + 40 => 1, + 41 => 1, + 42 => 1, + 43 => 1, + 44 => 1, + + 47 => 1, + 48 => 1, + 49 => 1, + 50 => 1, + 51 => 1, + + 54 => 1, + 55 => 1, + 56 => 1, + 57 => 1, + + 60 => 1, + + 63 => 1, + + 66 => 1, + 67 => 1, + 68 => 1, + 69 => 1, + 70 => 1, + 71 => 1, + 72 => 1, + 73 => 1, + 74 => 1, + 75 => 1, + 76 => 1, + ); + + } // end getErrorList() + + /** + * Returns the lines where warnings should occur. + * + * @return array => + */ + public function getWarningList() { + return array(); + + } + +} // End class. diff --git a/WordPress/Tests/Files/FileNameUnitTest.php b/WordPress/Tests/Files/FileNameUnitTest.php index e5f3f094c2..20b7e51110 100644 --- a/WordPress/Tests/Files/FileNameUnitTest.php +++ b/WordPress/Tests/Files/FileNameUnitTest.php @@ -1,67 +1,38 @@ - * @author Greg Sherwood - * @author Marc McIntyre - * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence - * @link http://pear.php.net/package/PHP_CodeSniffer + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ /** * Unit test class for the FileName sniff. * - * A sniff unit test checks a .inc file for expected violations of a single - * coding standard. Expected errors and warnings are stored in this class. - * - * @category PHP - * @package PHP_CodeSniffer - * @author Akeda Bagus - * @author Greg Sherwood - * @author Marc McIntyre - * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence - * @version Release: @package_version@ - * @link http://pear.php.net/package/PHP_CodeSniffer + * @package WPCS\WordPressCodingStandards + * @since 2013-06-11 */ -class WordPress_Tests_Files_FileNameUnitTest extends AbstractSniffUnitTest -{ - - - /** - * Returns the lines where errors should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of errors that should occur on that line. - * - * @return array(int => int) - */ - public function getErrorList() - { - return array(); - - }//end getErrorList() - +class WordPress_Tests_Files_FileNameUnitTest extends AbstractSniffUnitTest { - /** - * Returns the lines where warnings should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) - */ - public function getWarningList() - { - return array(); + /** + * Returns the lines where errors should occur. + * + * @return array => + */ + public function getErrorList() { + return array(); - }//end getWarningList() + } + /** + * Returns the lines where warnings should occur. + * + * @return array => + */ + public function getWarningList() { + return array(); -}//end class + } -?> +} // End class. diff --git a/WordPress/Tests/Functions/DontExtractUnitTest.inc b/WordPress/Tests/Functions/DontExtractUnitTest.inc new file mode 100644 index 0000000000..9ed5c3d2b2 --- /dev/null +++ b/WordPress/Tests/Functions/DontExtractUnitTest.inc @@ -0,0 +1,9 @@ + 1 ) ); // Bad. + +// Similarly named functions or methods however are fine. +my_extract(); // Ok. +My_Object::extract(); // Ok. +$this->extract(); // Ok. +$my_object->extract(); // Ok. diff --git a/WordPress/Tests/Functions/DontExtractUnitTest.php b/WordPress/Tests/Functions/DontExtractUnitTest.php new file mode 100644 index 0000000000..fa06e359d8 --- /dev/null +++ b/WordPress/Tests/Functions/DontExtractUnitTest.php @@ -0,0 +1,40 @@ + => + */ + public function getErrorList() { + return array( + 3 => 1, + ); + + } + + /** + * Returns the lines where warnings should occur. + * + * @return array => + */ + public function getWarningList() { + return array(); + + } + +} // End class. diff --git a/WordPress/Tests/NamingConventions/ValidFunctionNameUnitTest.inc b/WordPress/Tests/NamingConventions/ValidFunctionNameUnitTest.inc index d66445aeee..82aaef04e5 100644 --- a/WordPress/Tests/NamingConventions/ValidFunctionNameUnitTest.inc +++ b/WordPress/Tests/NamingConventions/ValidFunctionNameUnitTest.inc @@ -1,37 +1,104 @@ - * @author Greg Sherwood - * @author Marc McIntyre - * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence - * @link http://pear.php.net/package/PHP_CodeSniffer + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ /** * Unit test class for the ValidFunctionName sniff. * - * A sniff unit test checks a .inc file for expected violations of a single - * coding standard. Expected errors and warnings are stored in this class. - * - * @category PHP - * @package PHP_CodeSniffer - * @author Akeda Bagus - * @author Greg Sherwood - * @author Marc McIntyre - * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence - * @version Release: @package_version@ - * @link http://pear.php.net/package/PHP_CodeSniffer + * @package WPCS\WordPressCodingStandards + * @since 2013-06-11 */ -class WordPress_Tests_NamingConventions_ValidFunctionNameUnitTest extends AbstractSniffUnitTest -{ - - - /** - * Returns the lines where errors should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of errors that should occur on that line. - * - * @return array(int => int) - */ - public function getErrorList() - { - return array( - 3 => 1, - 13 => 1, - 15 => 1, - ); - - }//end getErrorList() - - - /** - * Returns the lines where warnings should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) - */ - public function getWarningList() - { - return array(); - - }//end getWarningList() - - -}//end class - -?> +class WordPress_Tests_NamingConventions_ValidFunctionNameUnitTest extends AbstractSniffUnitTest { + + /** + * Returns the lines where errors should occur. + * + * @return array => + */ + public function getErrorList() { + return array( + 3 => 1, + 9 => 1, + 13 => 1, + 15 => 1, + 79 => 1, + 80 => 1, + 81 => 1, + 82 => 1, + 83 => 1, + 84 => 1, + 85 => 1, + 86 => 1, + 87 => 1, + 88 => 1, + 89 => 1, + ); + + } + + /** + * Returns the lines where warnings should occur. + * + * @return array => + */ + public function getWarningList() { + return array(); + + } + +} // End class. diff --git a/WordPress/Tests/NamingConventions/ValidHookNameUnitTest.1.inc b/WordPress/Tests/NamingConventions/ValidHookNameUnitTest.1.inc new file mode 100644 index 0000000000..084a176612 --- /dev/null +++ b/WordPress/Tests/NamingConventions/ValidHookNameUnitTest.1.inc @@ -0,0 +1,17 @@ +screen->id}", $this->_actions ); +apply_filters( "current_theme-supports-{$feature}", true, $args, $_wp_theme_features[$feature] ); + +// These should still give warnings. +do_action( "admin_head*$hook_suffix" ); // Warning - use underscore. +do_action( 'admin_head.media.upload_popup' ); // Warning - use underscore. +apply_filters( "bulk_actions {$this->screen->id}", $this->_actions ); // Warning - use underscore. +apply_filters( "current_theme/supports-{$feature}", true, $args, $_wp_theme_features[$feature] ); // Warning - use underscore. + +// @codingStandardsChangeSetting WordPress.NamingConventions.ValidHookName additionalWordDelimiters _ diff --git a/WordPress/Tests/NamingConventions/ValidHookNameUnitTest.2.inc b/WordPress/Tests/NamingConventions/ValidHookNameUnitTest.2.inc new file mode 100644 index 0000000000..e58cc75781 --- /dev/null +++ b/WordPress/Tests/NamingConventions/ValidHookNameUnitTest.2.inc @@ -0,0 +1,17 @@ +screen->id}", $this->_actions ); +apply_filters( "current_theme/supports-{$feature}", true, $args, $_wp_theme_features[$feature] ); + +// These should still give warnings. +do_action( "admin_head*$hook_suffix" ); // Warning - use underscore. +do_action( 'admin_head&media+upload_popup' ); // Warning - use underscore. +apply_filters( "bulk_actions {$this->screen->id}", $this->_actions ); // Warning - use underscore. +apply_filters( "current_theme#supports-{$feature}", true, $args, $_wp_theme_features[$feature] ); // Warning - use underscore. + +// @codingStandardsChangeSetting WordPress.NamingConventions.ValidHookName additionalWordDelimiters _ diff --git a/WordPress/Tests/NamingConventions/ValidHookNameUnitTest.inc b/WordPress/Tests/NamingConventions/ValidHookNameUnitTest.inc new file mode 100644 index 0000000000..bda73caaf5 --- /dev/null +++ b/WordPress/Tests/NamingConventions/ValidHookNameUnitTest.inc @@ -0,0 +1,85 @@ +do_action( 'someAction' ); // Ok - not WP do_action. +SomeClass::do_action( 'someAction' ); // Ok - not WP do_action. +prefix_do_action( 'someAction' ); // Ok - not WP do_action. + +// Check for incorrect word separators. +do_action( "admin_head-$hook_suffix" ); // Warning - use underscore. +do_action( 'admin_head.media.upload_popup' ); // Warning - use underscore. +apply_filters( "bulk_actions {$this->screen->id}", $this->_actions ); // Warning - use underscore. +apply_filters( "current_theme/supports-{$feature}", true, $args, $_wp_theme_features[$feature] ); // Warning - use underscore. + +// Simple strings. +do_action( "adminHead" ); // Error - use lowercase. +do_action_ref_array( 'ADMINHEAD', array( $variable ) ); // Error - use lowercase. +apply_filters( 'adminHead', $variable ); // Error - use lowercase. +apply_filters_ref_array( 'ADMINHEAD', array( $variable ) ); // Error - use lowercase. + +// Variable hooks. +do_action( $Hook_name ); // Ok. +do_action( "{$Hook_Name}" ); // Ok. + +// Compound hook names. +do_action( 'admin_head_' . $Type . '_action' ); // ok. +do_action( 'admin_head_' . get_ID() . '_action' ); // Ok. +do_action( 'admin_head_' . $post->ID . '_action' ); // Ok. + +do_action( 'admin_Head_' . $Type . '_Action' ); // Error - use lowercase. +do_action( 'admin_Head_' . get_ID() . '_Action' ); // Error - use lowercase. +do_action( 'admin_Head_' . $post->ID . '_Action' ); // Error - use lowercase. + +do_action( + 'admin_Head_' . $type, + $variable +); // Error - use lowercase. + +// More complex strings. +do_action( "admin_head_$Post" ); // Ok. +do_action( "admin_head_$Post[1]_action" ); // Ok. +do_action( "admin_head_$Post[Test]_action" ); // Ok. +do_action( "admin_head_${Post}_action" ); // Ok. +do_action( "admin_head_$Post->ID" ); // Ok. +do_action( "admin_head_{$Post}" ); // Ok. +do_action( "admin_head_{$Post['Key']}_action" ); // Ok. +do_action( "admin_head_{$Post[1][2]}_action" ); // Ok. +do_action( "admin_head_{$post->ID}_action" ); // Ok. +do_action( "admin_head_{$obj->Values[3]->name}_action" ); // Ok. +do_action( "admin_head_{${$Name}}_action" ); // Ok. +do_action( "admin_head_{$foo->{$baz[1]}}_action" ); // Ok. +do_action( "admin_head_{${getName()}}_action" ); // Ok. +do_action( "admin_head_{${$object->getName()}}_action" ); // Ok. + +do_action( "admin_Head_$Post" ); // Error - use lowercase. +do_action( "admin_Head_$Post[1]_Action" ); // Error - use lowercase. +do_action( "admin_Head_$Post[Test]_Action" ); // Error - use lowercase. +do_action( "admin_Head_${Post}_Action" ); // Error - use lowercase. +do_action( "admin_Head_$Post->ID" ); // Error - use lowercase. +do_action( "admin_Head_{$Post}" ); // Error - use lowercase. +do_action( "admin_Head_{$Post['Key']}_Action" ); // Error - use lowercase. +do_action( "admin_Head_{$Post[1][2]}_Action" ); // Error - use lowercase. +do_action( "admin_Head_{$post->ID}_Action" ); // Error - use lowercase. +do_action( "admin_Head_{$obj->Values[3]->name}_Action" ); // Error - use lowercase. +do_action( "admin_Head_{${$Name}}_Action" ); // Error - use lowercase. +do_action( "admin_Head_{$foo->{$baz[1]}}_Action" ); // Error - use lowercase. +do_action( "admin_Head_{${getName()}}_Action" ); // Error - use lowercase. +do_action( "admin_Head_{${$object->getName()}}_Action" ); // Error - use lowercase. + +do_action( "admin_Head_$Post admin_Head_$Post" ); // Error - use lowercase + warning about space. +do_action( "admin_Head_$Post[1]_Action_$Post[1]_Action" ); // Error - use lowercase. +do_action( "admin_Head_$Post[Test]_Action_$Post[Test]_Action" ); // Error - use lowercase. +do_action( "admin_Head_${Post}_Action_${Post}_Action" ); // Error - use lowercase. +do_action( "admin_Head_$Post->ID admin_Head_$Post->ID" ); // Error - use lowercase + warning about space. +do_action( "admin_Head_{$Post}_admin_Head_{$Post}" ); // Error - use lowercase. +do_action( "admin_Head_{$Post['Key']}_Action_{$Post['Key']}_Action" ); // Error - use lowercase. +do_action( "admin_Head_{$Post[1][2]}_Action_{$Post[1][2]}_Action" ); // Error - use lowercase. +do_action( "admin_Head_{$post->ID}_Action_{$post->ID}_Action" ); // Error - use lowercase. +do_action( "admin_Head_{$obj->Values[3]->name}-Action_{$obj->Values[3]->name}_Action" ); // Error - use lowercase + warning about dash. +do_action( "admin_Head_{${$Name}}_Action_{${$Name}}_Action" ); // Error - use lowercase. +do_action( "admin_Head_{$foo->{$baz[1]}}_Action_{$foo->{$baz[1]}}_Action" ); // Error - use lowercase. +do_action( "admin_Head_{${getName()}}_Action_{${getName()}}_Action" ); // Error - use lowercase. +do_action( "admin_Head_{${$object->getName()}}_Action_{${$object->getName()}}_Action" ); // Error - use lowercase. + +// Make sure that deprecated hook names are ignored for this sniff. +do_action_deprecated( "admin_Head_$Post admin_Head_$Post" ); // Ok. +apply_filters_deprecated( "admin_Head_$Post->ID admin_Head_$Post->ID" ); // Ok. diff --git a/WordPress/Tests/NamingConventions/ValidHookNameUnitTest.php b/WordPress/Tests/NamingConventions/ValidHookNameUnitTest.php new file mode 100644 index 0000000000..f571579194 --- /dev/null +++ b/WordPress/Tests/NamingConventions/ValidHookNameUnitTest.php @@ -0,0 +1,112 @@ + => + */ + public function getErrorList( $testFile = 'ValidHookNameUnitTest.inc' ) { + + switch ( $testFile ) { + case 'ValidHookNameUnitTest.inc': + return array( + 14 => 1, + 15 => 1, + 16 => 1, + 17 => 1, + 28 => 1, + 29 => 1, + 30 => 1, + 32 => 1, + 53 => 1, + 54 => 1, + 55 => 1, + 56 => 1, + 57 => 1, + 58 => 1, + 59 => 1, + 60 => 1, + 61 => 1, + 62 => 1, + 63 => 1, + 64 => 1, + 65 => 1, + 66 => 1, + 68 => 1, + 69 => 1, + 70 => 1, + 71 => 1, + 72 => 1, + 73 => 1, + 74 => 1, + 75 => 1, + 76 => 1, + 77 => 1, + 78 => 1, + 79 => 1, + 80 => 1, + 81 => 1, + ); + + case 'ValidHookNameUnitTest.1.inc': + case 'ValidHookNameUnitTest.2.inc': + default: + return array(); + + } // end switch + + } // end getErrorList() + + /** + * Returns the lines where warnings should occur. + * + * @param string $testFile The name of the file being tested. + * @return array => + */ + public function getWarningList( $testFile = 'ValidHookNameUnitTest.inc' ) { + + switch ( $testFile ) { + case 'ValidHookNameUnitTest.inc': + return array( + 8 => 1, + 9 => 1, + 10 => 1, + 11 => 1, + 68 => 1, + 72 => 1, + 77 => 1, + ); + + case 'ValidHookNameUnitTest.1.inc': + case 'ValidHookNameUnitTest.2.inc': + return array( + 12 => 1, + 13 => 1, + 14 => 1, + 15 => 1, + ); + + default: + return array(); + + } + + } + +} // End class. diff --git a/WordPress/Tests/NamingConventions/ValidVariableNameUnitTest.inc b/WordPress/Tests/NamingConventions/ValidVariableNameUnitTest.inc index 61234a9334..80a2477d51 100644 --- a/WordPress/Tests/NamingConventions/ValidVariableNameUnitTest.inc +++ b/WordPress/Tests/NamingConventions/ValidVariableNameUnitTest.inc @@ -1,46 +1,46 @@ varName2; // Bad +echo $this->varName2; // Bad. echo $this->var_name2; echo $this->varname2; -echo $this->_varName2; // Bad -echo $object->varName2; // Bad +echo $this->_varName2; // Bad. +echo $object->varName2; // Bad. echo $object->var_name2; echo $object_name->varname2; -echo $object_name->_varName2; // Bad +echo $object_name->_varName2; // Bad. +echo $object_name->VAR_name; // Bad. echo $this->myFunction($one, $two); echo $object->myFunction($one_two); -$error = "format is \$GLOBALS['$varName']"; // Bad +$error = "format is \$GLOBALS['$varName']"; // Bad. echo $_SESSION['var_name']; echo $_FILES['var_name']; echo $_ENV['var_name']; echo $_COOKIE['var_name']; -$XML = 'hello'; // Bad -$myXML = 'hello'; // Bad -$XMLParser = 'hello'; // Bad -$xmlParser = 'hello'; // Bad +$XML = 'hello'; // Bad. +$myXML = 'hello'; // Bad. +$XMLParser = 'hello'; // Bad. +$xmlParser = 'hello'; // Bad. -$ID = 1; // Bad +$ID = 1; // Bad. $post = get_post( $x ); echo $post->ID; -echo $comment_ID; // Bad -echo $comment_post_ID; // Bad -echo $comment_author_IP; // Bad +echo $comment_ID; // Bad. +echo $comment_post_ID; // Bad. +echo $comment_author_IP; // Bad. $comment = get_comment( 1 ); echo $comment->comment_ID; @@ -93,4 +95,28 @@ echo $comment->comment_author_IP; class Foo { public $_public_leading_underscore; private $private_no_underscore_loading; + + function Bar( $VARname ) { // Bad. + $localVariable = false; // Bad. + echo Some_Class::$VarName; // Bad. + echo $this->VAR_name; // Bad. + $_localVariable = false; // Bad. + echo Some_Class::$_VarName; // Bad. + echo $this->_VAR_name; // Bad. + } + + function Baz( $var_name ) { // Ok. + $local_variable = false; // Ok. + echo Some_Class::$var_name; // Ok. + echo $this->var_name; // Ok. + $_local_variable = false; // Ok. + echo Some_Class::$_var_name; // Ok. + echo $this->_var_name; // Ok. + } +} + +if ( is_category() ) { + $category = get_queried_object(); + $cat_id = $category->cat_ID; + $cat_ID = $category->cat_ID; // Bad. } diff --git a/WordPress/Tests/NamingConventions/ValidVariableNameUnitTest.php b/WordPress/Tests/NamingConventions/ValidVariableNameUnitTest.php index ed46bf07d6..33cf777902 100644 --- a/WordPress/Tests/NamingConventions/ValidVariableNameUnitTest.php +++ b/WordPress/Tests/NamingConventions/ValidVariableNameUnitTest.php @@ -1,44 +1,24 @@ - * @author Marc McIntyre - * @author Weston Ruter - * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600) - * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence - * @link http://pear.php.net/package/PHP_CodeSniffer + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ /** - * Unit test class for WordPress_Sniffs_NamingConventions_ValidVariableNameSniff. - * - * A sniff unit test checks a .inc file for expected violations of a single - * coding standard. Expected errors and warnings are stored in this class. + * Unit test class for the ValidVariableName sniff. * - * @category PHP - * @package PHP_CodeSniffer - * @author Greg Sherwood - * @author Marc McIntyre - * @author Weston Ruter - * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600) - * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence - * @version Release: @package_version@ - * @link http://pear.php.net/package/PHP_CodeSniffer + * @package WPCS\WordPressCodingStandards + * @since 0.9.0 */ class WordPress_Tests_NamingConventions_ValidVariableNameUnitTest extends AbstractSniffUnitTest { /** * Returns the lines where errors should occur. * - * The key of the array should represent the line number and the value - * should represent the number of errors that should occur on that line. - * - * @return array + * @return array => */ public function getErrorList() { $errors = array( @@ -60,34 +40,43 @@ public function getErrorList() { 43 => 1, 51 => 1, 54 => 1, - 56 => 1, - 59 => 1, + 55 => 1, + 57 => 1, 60 => 1, - 63 => 1, - 68 => 1, - 75 => 1, - 76 => 1, + 61 => 1, + 64 => 1, + 65 => 1, + 70 => 1, 77 => 1, 78 => 1, + 79 => 1, 80 => 1, - 84 => 1, - 85 => 1, + 82 => 1, 86 => 1, + 87 => 1, + 88 => 1, + 99 => 1, + 100 => 1, + 101 => 1, + 102 => 1, + 103 => 1, + 104 => 1, + 105 => 1, + 121 => 1, ); return $errors; - }//end getErrorList() + } // end getErrorList() /** * Returns the lines where warnings should occur. * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array + * @return array => */ public function getWarningList() { return array(); + } -}//end class + +} // End class. diff --git a/WordPress/Tests/PHP/DisallowAlternativePHPTagsUnitTest.inc b/WordPress/Tests/PHP/DisallowAlternativePHPTagsUnitTest.inc new file mode 100644 index 0000000000..0f3daa6cee --- /dev/null +++ b/WordPress/Tests/PHP/DisallowAlternativePHPTagsUnitTest.inc @@ -0,0 +1,18 @@ +
+ +Some content here. +<% echo $var; %> +

Some text <% echo $var; %> and some more text

+<%= $var . ' and some more text to make sure the snippet works'; %> +

Some text <%= $var %> and some more text

+ + + + +
diff --git a/WordPress/Tests/PHP/DisallowAlternativePHPTagsUnitTest.inc.fixed b/WordPress/Tests/PHP/DisallowAlternativePHPTagsUnitTest.inc.fixed new file mode 100644 index 0000000000..2b1c151387 --- /dev/null +++ b/WordPress/Tests/PHP/DisallowAlternativePHPTagsUnitTest.inc.fixed @@ -0,0 +1,18 @@ +
+ +Some content here. + +

Some text and some more text

+ +

Some text and some more text

+ + + + +
diff --git a/WordPress/Tests/PHP/DisallowAlternativePHPTagsUnitTest.php b/WordPress/Tests/PHP/DisallowAlternativePHPTagsUnitTest.php new file mode 100644 index 0000000000..e661908ef9 --- /dev/null +++ b/WordPress/Tests/PHP/DisallowAlternativePHPTagsUnitTest.php @@ -0,0 +1,88 @@ +asp_tags = (bool) ini_get( 'asp_tags' ); + } + } + + /** + * Skip this test on HHVM. + * + * @return bool Whether to skip this test. + */ + protected function shouldSkipTest() { + return defined( 'HHVM_VERSION' ); + } + + /** + * Returns the lines where errors should occur. + * + * @return array => + */ + public function getErrorList() { + $errors = array( + 8 => 1, + 11 => 1, + 12 => 1, + 15 => 1, + ); + + if ( true === $this->asp_tags ) { + $errors[4] = 1; + $errors[5] = 1; + $errors[6] = 1; + $errors[7] = 1; + } + + return $errors; + } + + /** + * Returns the lines where warnings should occur. + * + * @return array => + */ + public function getWarningList() { + $warnings = array(); + + if ( false === $this->asp_tags ) { + $warnings = array( + 4 => 1, + 5 => 1, + 6 => 1, + 7 => 1, + ); + } + + return $warnings; + } + +} // End class. diff --git a/WordPress/Tests/PHP/DiscouragedFunctionsUnitTest.inc b/WordPress/Tests/PHP/DiscouragedFunctionsUnitTest.inc index 2852bfcd72..b86c3f0377 100644 --- a/WordPress/Tests/PHP/DiscouragedFunctionsUnitTest.inc +++ b/WordPress/Tests/PHP/DiscouragedFunctionsUnitTest.inc @@ -1,33 +1,15 @@ - * @author Greg Sherwood - * @author Marc McIntyre - * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence - * @link http://pear.php.net/package/PHP_CodeSniffer + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ /** - * Unit test class for the DiscouragedFunctions sniff. - * - * A sniff unit test checks a .inc file for expected violations of a single - * coding standard. Expected errors and warnings are stored in this class. + * Unit test class for the PHP_DiscouragedFunctions sniff. * - * @category PHP - * @package PHP_CodeSniffer - * @author Akeda Bagus - * @author Greg Sherwood - * @author Marc McIntyre - * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence - * @version Release: @package_version@ - * @link http://pear.php.net/package/PHP_CodeSniffer + * @package WPCS\WordPressCodingStandards + * @since 2013-06-11 */ -class WordPress_Tests_PHP_DiscouragedFunctionsUnitTest extends AbstractSniffUnitTest -{ - - - /** - * Returns the lines where errors should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of errors that should occur on that line. - * - * @return array(int => int) - */ - public function getErrorList() - { - return array(); - - }//end getErrorList() - - - /** - * Returns the lines where warnings should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) - */ - public function getWarningList() - { - return array( - 8 => 1, - 9 => 1, - 17 => 1, - 20 => 1, - 23 => 1, - 25 => 1, - 27 => 1, - 33 => 1, - 35 => 1, - 37 => 1, - 39 => 1, - 41 => 1, - 43 => 1, - 45 => 1, - 47 => 1, - 49 => 1, - 51 => 1, - 53 => 1, - 55 => 1, - 63 => 1, - 65 => 1, - 70 => 1, - 72 => 1, - ); - - }//end getWarningList() - - -}//end class - -?> +class WordPress_Tests_PHP_DiscouragedFunctionsUnitTest extends AbstractSniffUnitTest { + + /** + * Returns the lines where errors should occur. + * + * @return array => + */ + public function getErrorList() { + return array(); + + } + + /** + * Returns the lines where warnings should occur. + * + * @return array => + */ + public function getWarningList() { + return array( + 8 => 1, + 9 => 1, + 15 => 1, + 17 => 1, + 19 => 1, + 21 => 1, + 23 => 1, + 25 => 1, + 27 => 1, + 29 => 1, + 31 => 1, + 33 => 1, + 35 => 1, + 37 => 1, + 39 => 1, + 45 => 1, + 47 => 1, + 52 => 1, + 54 => 1, + ); + + } + +} // End class. diff --git a/WordPress/Tests/PHP/POSIXFunctionsUnitTest.inc b/WordPress/Tests/PHP/POSIXFunctionsUnitTest.inc new file mode 100644 index 0000000000..785779e02b --- /dev/null +++ b/WordPress/Tests/PHP/POSIXFunctionsUnitTest.inc @@ -0,0 +1,26 @@ + => + */ + public function getErrorList() { + return array( + 13 => 1, + 16 => 1, + 18 => 1, + 20 => 1, + 22 => 1, + 24 => 1, + 26 => 1, + ); + + } + + /** + * Returns the lines where warnings should occur. + * + * @return array => + */ + public function getWarningList() { + return array(); + + } + +} // End class. diff --git a/WordPress/Tests/PHP/StrictComparisonsUnitTest.inc b/WordPress/Tests/PHP/StrictComparisonsUnitTest.inc index 73030baf36..1cb1fe41b7 100644 --- a/WordPress/Tests/PHP/StrictComparisonsUnitTest.inc +++ b/WordPress/Tests/PHP/StrictComparisonsUnitTest.inc @@ -1,21 +1,21 @@ $true ) { // Bad +} elseif ( true <> $true ) { // Bad. echo 'False'; -} elseif ( false !== $true ) { // OK +} elseif ( false !== $true ) { // Ok. echo 'False'; } -// test for whitelisting -if ( true == $true ) { // loose comparison, OK +// Test for whitelisting. +if ( true == $true ) { // Loose comparison, OK. echo 'True'; } \ No newline at end of file diff --git a/WordPress/Tests/PHP/StrictComparisonsUnitTest.php b/WordPress/Tests/PHP/StrictComparisonsUnitTest.php index c2cadfdab6..1de1ad161e 100644 --- a/WordPress/Tests/PHP/StrictComparisonsUnitTest.php +++ b/WordPress/Tests/PHP/StrictComparisonsUnitTest.php @@ -1,65 +1,42 @@ int) - */ - public function getErrorList() - { - return array(); - - }//end getErrorList() - - - /** - * Returns the lines where warnings should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) - */ - public function getWarningList() - { - return array( - 3 => 1, - 10 => 1, - 12 => 1, - ); - - }//end getWarningList() - - -}//end class +class WordPress_Tests_PHP_StrictComparisonsUnitTest extends AbstractSniffUnitTest { + + /** + * Returns the lines where errors should occur. + * + * @return array => + */ + public function getErrorList() { + return array(); + + } + + /** + * Returns the lines where warnings should occur. + * + * @return array => + */ + public function getWarningList() { + return array( + 3 => 1, + 10 => 1, + 12 => 1, + ); + + } + +} // End class. diff --git a/WordPress/Tests/PHP/StrictInArrayUnitTest.inc b/WordPress/Tests/PHP/StrictInArrayUnitTest.inc index a0522f0a0d..4832b9d50c 100644 --- a/WordPress/Tests/PHP/StrictInArrayUnitTest.inc +++ b/WordPress/Tests/PHP/StrictInArrayUnitTest.inc @@ -1,20 +1,40 @@ in_array( 1, array( '1', 1, true ) ); // OK +$bar->in_array( 1, array( '1', 1, true ) ); // Ok. $bar-> - in_array( 1, array( '1', 1, true ) ); // OK + in_array( 1, array( '1', 1, true ) ); // Ok. -in_array(); // Error +in_array(); // Error. + + +array_search( 1, $array, true ); // Ok. +$my->array_search( $array, $needle ); // Ok. + +array_search( 1, $array, false ); // Warning. +array_search( 1, $array ); // Warning. +Array_Search( 1, $array ); // Warning. +ARRAY_SEARCH( 1, array( '1', 1, true ) ); // Warning. + + +array_keys( $testing ); // Ok. +array_keys( array( '1', 1, true ) ); // Ok. +array_keys( $testing, 'my_key', true ); // Ok. +array_keys( array( '1', 1, true ), 'my_key', true ); // Ok. + +array_keys( $testing, 'my_key' ); // Warning. +array_keys( array( '1', 1, true ), 'my_key' ); // Warning. +array_keys( $testing, 'my_key', false ); // Warning. +array_keys( array( '1', 1, true ), 'my_key', false ); // Warning. diff --git a/WordPress/Tests/PHP/StrictInArrayUnitTest.php b/WordPress/Tests/PHP/StrictInArrayUnitTest.php index cff211578f..25738ba2b8 100644 --- a/WordPress/Tests/PHP/StrictInArrayUnitTest.php +++ b/WordPress/Tests/PHP/StrictInArrayUnitTest.php @@ -1,34 +1,24 @@ int) + * @return array => */ public function getErrorList() { return array( @@ -40,16 +30,22 @@ public function getErrorList() { /** * Returns the lines where warnings should occur. * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) + * @return array => */ public function getWarningList() { return array( 5 => 1, 9 => 1, 10 => 1, + 26 => 1, + 27 => 1, + 28 => 1, + 29 => 1, + 37 => 1, + 38 => 1, + 39 => 1, + 40 => 1, ); } -} + +} // End class. diff --git a/WordPress/Tests/PHP/YodaConditionsUnitTest.inc b/WordPress/Tests/PHP/YodaConditionsUnitTest.inc index 308649e663..5b2cf5e43a 100644 --- a/WordPress/Tests/PHP/YodaConditionsUnitTest.inc +++ b/WordPress/Tests/PHP/YodaConditionsUnitTest.inc @@ -1,92 +1,92 @@ num_rows === 0 ) {} // Bad +if ( $GLOBALS['wpdb']->num_rows === 0 ) {} // Bad. -if ( $true == strtolower( $check ) ) {} // Bad +if ( $true == strtolower( $check ) ) {} // Bad. -$update = 'yes' === strtolower( $this->from_post( 'update' ) ); // OK +$update = 'yes' === strtolower( $this->from_post( 'update' ) ); // Ok. diff --git a/WordPress/Tests/PHP/YodaConditionsUnitTest.php b/WordPress/Tests/PHP/YodaConditionsUnitTest.php index 5ad72316ad..bdf509621c 100644 --- a/WordPress/Tests/PHP/YodaConditionsUnitTest.php +++ b/WordPress/Tests/PHP/YodaConditionsUnitTest.php @@ -1,77 +1,52 @@ int) - */ - public function getErrorList() - { - return array( - 2 => 2, - 4 => 2, - 11 => 1, - 18 => 1, - 25 => 1, - 32 => 1, - 49 => 1, - 55 => 1, - 62 => 1, - 68 => 1, - 84 => 1, - 88 => 1, - 90 => 1, - ); - - }//end getErrorList() - - - /** - * Returns the lines where warnings should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) - */ - public function getWarningList() - { - return array(); - - }//end getWarningList() - - -}//end class - -?> +class WordPress_Tests_PHP_YodaConditionsUnitTest extends AbstractSniffUnitTest { + + /** + * Returns the lines where errors should occur. + * + * @return array => + */ + public function getErrorList() { + return array( + 2 => 2, + 4 => 2, + 11 => 1, + 18 => 1, + 25 => 1, + 32 => 1, + 49 => 1, + 55 => 1, + 62 => 1, + 68 => 1, + 84 => 1, + 88 => 1, + 90 => 1, + ); + + } + + /** + * Returns the lines where warnings should occur. + * + * @return array => + */ + public function getWarningList() { + return array(); + + } + +} // End class. diff --git a/WordPress/Tests/VIP/AdminBarRemovalUnitTest.php b/WordPress/Tests/VIP/AdminBarRemovalUnitTest.php index a1a904b175..0634f529bf 100644 --- a/WordPress/Tests/VIP/AdminBarRemovalUnitTest.php +++ b/WordPress/Tests/VIP/AdminBarRemovalUnitTest.php @@ -1,48 +1,41 @@ + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ -class WordPress_Tests_VIP_AdminBarRemovalUnitTest extends AbstractSniffUnitTest -{ - /** - * Returns the lines where errors should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of errors that should occur on that line. - * - * @return array(int => int) - */ - public function getErrorList() - { - return array( - 3 => 1, - 5 => 1, - ); - - }//end getErrorList() - - - /** - * Returns the lines where warnings should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) - */ - public function getWarningList() - { - return array(); - - }//end getWarningList() - - -}//end class - -?> +/** + * Unit test class for the AdminBarRemoval sniff. + * + * @package WPCS\WordPressCodingStandards + * @since 0.3.0 + */ +class WordPress_Tests_VIP_AdminBarRemovalUnitTest extends AbstractSniffUnitTest { + + /** + * Returns the lines where errors should occur. + * + * @return array => + */ + public function getErrorList() { + return array( + 3 => 1, + 5 => 1, + ); + + } + + /** + * Returns the lines where warnings should occur. + * + * @return array => + */ + public function getWarningList() { + return array(); + + } + +} // End class. diff --git a/WordPress/Tests/VIP/CronIntervalUnitTest.inc b/WordPress/Tests/VIP/CronIntervalUnitTest.inc index 183c4eaea4..d4bc9dbd37 100644 --- a/WordPress/Tests/VIP/CronIntervalUnitTest.inc +++ b/WordPress/Tests/VIP/CronIntervalUnitTest.inc @@ -25,7 +25,7 @@ class Foo { static function my_add_quicklier( $schedules ) { $schedules['every_5_mins'] = array( - 'interval' => 20 * 60 - 15 * 60, // sneaky 5 minute interval + 'interval' => 20 * 60 - 15 * 60, // Sneaky 5 minute interval. 'display' => __( 'Once every 5 minutes' ) ); return $schedules; diff --git a/WordPress/Tests/VIP/CronIntervalUnitTest.php b/WordPress/Tests/VIP/CronIntervalUnitTest.php index a1378c2422..bbeca06dff 100644 --- a/WordPress/Tests/VIP/CronIntervalUnitTest.php +++ b/WordPress/Tests/VIP/CronIntervalUnitTest.php @@ -1,50 +1,45 @@ + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ -class WordPress_Tests_VIP_CronIntervalUnitTest extends AbstractSniffUnitTest -{ - /** - * Returns the lines where errors should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of errors that should occur on that line. - * - * @return array(int => int) - */ - public function getErrorList() - { - return array( - 10 => 1, - 15 => 1, - 35 => 1, - 39 => 1, - ); - - }//end getErrorList() +/** + * Unit test class for the CronInterval sniff. + * + * @package WPCS\WordPressCodingStandards + * @since 0.3.0 + */ +class WordPress_Tests_VIP_CronIntervalUnitTest extends AbstractSniffUnitTest { + /** + * Returns the lines where errors should occur. + * + * @return array => + */ + public function getErrorList() { + return array( + 10 => 1, + 15 => 1, + 35 => 1, + 39 => 1, + ); - /** - * Returns the lines where warnings should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) - */ - public function getWarningList() - { - return array( - 37 => 1, - ); + } - }//end getWarningList() + /** + * Returns the lines where warnings should occur. + * + * @return array => + */ + public function getWarningList() { + return array( + 37 => 1, + ); + } -}//end class +} // End class. diff --git a/WordPress/Tests/VIP/DirectDatabaseQueryUnitTest.inc b/WordPress/Tests/VIP/DirectDatabaseQueryUnitTest.inc index 1cfe139e86..e44b14358c 100644 --- a/WordPress/Tests/VIP/DirectDatabaseQueryUnitTest.inc +++ b/WordPress/Tests/VIP/DirectDatabaseQueryUnitTest.inc @@ -3,9 +3,9 @@ function foo() { global $wpdb; - $listofthings = $wpdb->get_col( 'SELECT something FROM somewhere WHERE someotherthing = 1' ); // Error + Warning + $listofthings = $wpdb->get_col( 'SELECT something FROM somewhere WHERE someotherthing = 1' ); // Error + Warning. - $listofthings = $wpdb->get_col( 'SELECT something FROM somewhere WHERE someotherthing = 1' ); //db call okay ( No Warning, but Error for not caching! ) + $listofthings = $wpdb->get_col( 'SELECT something FROM somewhere WHERE someotherthing = 1' ); // DB call okay ( No Warning, but Error for not caching! ). return $listofthings; } @@ -14,7 +14,7 @@ function bar() { global $wpdb; if ( ! ( $listofthings = wp_cache_get( $foo ) ) ) { - $listofthings = $wpdb->get_col( 'SELECT something FROM somewhere WHERE someotherthing = 1' ); // Warning + $listofthings = $wpdb->get_col( 'SELECT something FROM somewhere WHERE someotherthing = 1' ); // Warning. wp_cache_set( 'foo', $listofthings ); } @@ -29,11 +29,11 @@ function baz() { $baz = wp_cache_get( 'baz' ); if ( false !== $baz ) { - $wpdb->query( 'ALTER TABLE TO ADD SOME FIELDS' ); // db call okay (but not really because ALTER TABLE!) + $wpdb->query( 'ALTER TABLE TO ADD SOME FIELDS' ); // DB call okay (but not really because ALTER TABLE!). - $wpdb->query( $wpdb->prepare( 'CREATE TABLE ' ) ); // db call okay (but not really because CREATE TABLE!) + $wpdb->query( $wpdb->prepare( 'CREATE TABLE ' ) ); // DB call okay (but not really because CREATE TABLE!). - $wpdb->query( 'SELECT QUERY' ); // db call okay + $wpdb->query( 'SELECT QUERY' ); // DB call okay. $baz = $wpdb->get_results( $wpdb->prepare( 'SELECT X FROM Y ' ) ); @@ -47,20 +47,20 @@ function quux() { global $wpdb; $quux = wp_cache_get( 'quux' ); if ( false !== $quux ) { - $quux = $wpdb->get_results( $wpdb->prepare( 'SELECT X FROM Y ' ) ); // Bad, no wp_cache_set, results in Error + Warning + $quux = $wpdb->get_results( $wpdb->prepare( 'SELECT X FROM Y ' ) ); // Bad, no wp_cache_set, results in Error + Warning. } } function barzd() { global $wpdb; - $autoload = $wpdb->get_var( $wpdb->prepare( "SELECT autoload FROM $wpdb->options WHERE option_name = %s", $option_name ) ); // db call ok; no-cache ok + $autoload = $wpdb->get_var( $wpdb->prepare( "SELECT autoload FROM $wpdb->options WHERE option_name = %s", $option_name ) ); // DB call ok; no-cache ok. } function taz() { /* @var wpdb $wpdb */ global $wpdb; - echo $wpdb->insert_id; // Good, no actual call, and doesn't need any caching + echo $wpdb->insert_id; // Good, no actual call, and doesn't need any caching. } // Some $wpdb methods can pass with only deleting the cache. @@ -70,14 +70,14 @@ function cache_delete_only() { $data = $where = array(); // These methods are allowed to be used with just wp_cache_delete(). - $wpdb->update( $wpdb->users, $data, $where ); // db call ok; OK - $wpdb->replace( $wpdb->users, $data, $where ); // db call ok; OK - $wpdb->delete( $wpdb->users, $data, $where ); // db call ok; OK - $wpdb->query( 'SELECT X FROM Y' ); // db call ok; OK + $wpdb->update( $wpdb->users, $data, $where ); // DB call ok; OK. + $wpdb->replace( $wpdb->users, $data, $where ); // DB call ok; OK. + $wpdb->delete( $wpdb->users, $data, $where ); // DB call ok; OK. + $wpdb->query( 'SELECT X FROM Y' ); // DB call ok; OK. - $wpdb->get_results( 'SELECT X FROM Y' ); // db call ok; Bad - $wpdb->get_row( 'SELECT X FROM Y' ); // db call ok; Bad - $wpdb->get_col( 'SELECT X FROM Y' ); // db call ok; Bad + $wpdb->get_results( 'SELECT X FROM Y' ); // DB call ok; Bad. + $wpdb->get_row( 'SELECT X FROM Y' ); // DB call ok; Bad. + $wpdb->get_col( 'SELECT X FROM Y' ); // DB call ok; Bad. wp_cache_delete( 'key', 'group' ); } @@ -92,13 +92,13 @@ function cache_add_instead_of_set() { $data = $where = array(); - $wpdb->update( $wpdb->users, $data, $where ); // db call ok; OK - $wpdb->replace( $wpdb->users, $data, $where ); // db call ok; OK - $wpdb->delete( $wpdb->users, $data, $where ); // db call ok; OK - $wpdb->query( 'SELECT X FROM Y' ); // db call ok; OK - $wpdb->get_row( 'SELECT X FROM Y' ); // db call ok; OK - $wpdb->get_col( 'SELECT X FROM Y' ); // db call ok; OK - $baz = $wpdb->get_results( $wpdb->prepare( 'SELECT X FROM Y ' ) ); // db call ok; OK + $wpdb->update( $wpdb->users, $data, $where ); // DB call ok; OK. + $wpdb->replace( $wpdb->users, $data, $where ); // DB call ok; OK. + $wpdb->delete( $wpdb->users, $data, $where ); // DB call ok; OK. + $wpdb->query( 'SELECT X FROM Y' ); // DB call ok; OK. + $wpdb->get_row( 'SELECT X FROM Y' ); // DB call ok; OK. + $wpdb->get_col( 'SELECT X FROM Y' ); // DB call ok; OK. + $baz = $wpdb->get_results( $wpdb->prepare( 'SELECT X FROM Y ' ) ); // DB call ok; OK. wp_cache_add( 'baz', $baz ); } diff --git a/WordPress/Tests/VIP/DirectDatabaseQueryUnitTest.php b/WordPress/Tests/VIP/DirectDatabaseQueryUnitTest.php index f6bf3a376e..4b8da25df5 100644 --- a/WordPress/Tests/VIP/DirectDatabaseQueryUnitTest.php +++ b/WordPress/Tests/VIP/DirectDatabaseQueryUnitTest.php @@ -1,29 +1,26 @@ - * @link http://pear.php.net/package/PHP_CodeSniffer + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ -class WordPress_Tests_VIP_DirectDatabaseQueryUnitTest extends AbstractSniffUnitTest -{ - +/** + * Unit test class for the DirectDatabaseQuery sniff. + * + * @package WPCS\WordPressCodingStandards + * @since 0.3.0 + */ +class WordPress_Tests_VIP_DirectDatabaseQueryUnitTest extends AbstractSniffUnitTest { /** * Returns the lines where errors should occur. * - * The key of the array should represent the line number and the value - * should represent the number of errors that should occur on that line. - * - * @return array(int => int) + * @return array => */ - public function getErrorList() - { + public function getErrorList() { return array( 6 => 1, 8 => 1, @@ -33,29 +30,23 @@ public function getErrorList() 78 => 1, 79 => 1, 80 => 1, - ); - - }//end getErrorList() + ); + } /** * Returns the lines where warnings should occur. * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) + * @return array => */ - public function getWarningList() - { + public function getWarningList() { return array( 6 => 1, 17 => 1, 38 => 1, 50 => 1, - ); - - }//end getWarningList() + ); + } -}//end class +} // End class. diff --git a/WordPress/Tests/VIP/FileSystemWritesDisallowUnitTest.php b/WordPress/Tests/VIP/FileSystemWritesDisallowUnitTest.php index 1802354e06..0b13aa5da7 100644 --- a/WordPress/Tests/VIP/FileSystemWritesDisallowUnitTest.php +++ b/WordPress/Tests/VIP/FileSystemWritesDisallowUnitTest.php @@ -1,54 +1,43 @@ - * @link http://pear.php.net/package/PHP_CodeSniffer + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ -class WordPress_Tests_VIP_FileSystemWritesDisallowUnitTest extends AbstractSniffUnitTest -{ - +/** + * Unit test class for the FileSystemWritesDisallow sniff. + * + * @package WPCS\WordPressCodingStandards + * @since 0.3.0 + */ +class WordPress_Tests_VIP_FileSystemWritesDisallowUnitTest extends AbstractSniffUnitTest { /** * Returns the lines where errors should occur. * - * The key of the array should represent the line number and the value - * should represent the number of errors that should occur on that line. - * - * @return array(int => int) + * @return array => */ - public function getErrorList() - { + public function getErrorList() { return array( 3 => 1, 9 => 1, 10 => 1, 12 => 1, - ); - - }//end getErrorList() + ); + } /** * Returns the lines where warnings should occur. * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) + * @return array => */ - public function getWarningList() - { + public function getWarningList() { return array(); - }//end getWarningList() - - -}//end class + } -?> +} // End class. diff --git a/WordPress/Tests/VIP/OrderByRandUnitTest.inc b/WordPress/Tests/VIP/OrderByRandUnitTest.inc index 289228d057..c680a98a8b 100644 --- a/WordPress/Tests/VIP/OrderByRandUnitTest.inc +++ b/WordPress/Tests/VIP/OrderByRandUnitTest.inc @@ -1,13 +1,13 @@ 'rand', // Bad - "orderby" => "rand", // Bad - "orderby" => "RAND", // Bad + 'orderby' => 'rand', // Bad. + "orderby" => "rand", // Bad. + "orderby" => "RAND", // Bad. ); -_query_posts( 'orderby=rand' ); // Bad +_query_posts( 'orderby=rand' ); // Bad. -$query_args['orderby'] = 'rand'; // Bad +$query_args['orderby'] = 'rand'; // Bad. -$query_args['orderby'] = 'date'; // OK +$query_args['orderby'] = 'date'; // Ok. diff --git a/WordPress/Tests/VIP/OrderByRandUnitTest.php b/WordPress/Tests/VIP/OrderByRandUnitTest.php index a2e50f16ba..5074d859c1 100644 --- a/WordPress/Tests/VIP/OrderByRandUnitTest.php +++ b/WordPress/Tests/VIP/OrderByRandUnitTest.php @@ -1,44 +1,44 @@ int) - */ - public function getErrorList() { - return array( - 4 => 1, - 5 => 1, - 6 => 1, - 9 => 1, - 11 => 1, - ); +/** + * Unit test class for the OrderByRand sniff. + * + * @package WPCS\WordPressCodingStandards + * @since 0.9.0 + */ +class WordPress_Tests_VIP_OrderByRandUnitTest extends AbstractSniffUnitTest { - }//end getErrorList() + /** + * Returns the lines where errors should occur. + * + * @return array => + */ + public function getErrorList() { + return array( + 4 => 1, + 5 => 1, + 6 => 1, + 9 => 1, + 11 => 1, + ); + } - /** - * Returns the lines where warnings should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) - */ - public function getWarningList() { - return array(); + /** + * Returns the lines where warnings should occur. + * + * @return array => + */ + public function getWarningList() { + return array(); - } //end getWarningList() + } -}//end class +} // End class. diff --git a/WordPress/Tests/VIP/PluginMenuSlugUnitTest.inc b/WordPress/Tests/VIP/PluginMenuSlugUnitTest.inc index e6669fe953..e4414e80e9 100644 --- a/WordPress/Tests/VIP/PluginMenuSlugUnitTest.inc +++ b/WordPress/Tests/VIP/PluginMenuSlugUnitTest.inc @@ -1,7 +1,7 @@ + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ -class WordPress_Tests_VIP_PluginMenuSlugUnitTest extends AbstractSniffUnitTest -{ - /** - * Returns the lines where errors should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of errors that should occur on that line. - * - * @return array(int => int) - */ - public function getErrorList() - { - return array( - 3 => 1, - 5 => 1, - ); - - }//end getErrorList() +/** + * Unit test class for the PluginMenuSlug sniff. + * + * @package WPCS\WordPressCodingStandards + * @since 0.3.0 + */ +class WordPress_Tests_VIP_PluginMenuSlugUnitTest extends AbstractSniffUnitTest { + /** + * Returns the lines where errors should occur. + * + * @return array => + */ + public function getErrorList() { + return array( + 3 => 1, + 5 => 1, + ); - /** - * Returns the lines where warnings should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) - */ - public function getWarningList() - { - return array( - ); + } - }//end getWarningList() + /** + * Returns the lines where warnings should occur. + * + * @return array => + */ + public function getWarningList() { + return array(); + } -}//end class +} // End class. diff --git a/WordPress/Tests/VIP/PostsPerPageUnitTest.inc b/WordPress/Tests/VIP/PostsPerPageUnitTest.inc index 7be7fc8a39..9fd7d8aa7f 100644 --- a/WordPress/Tests/VIP/PostsPerPageUnitTest.inc +++ b/WordPress/Tests/VIP/PostsPerPageUnitTest.inc @@ -1,18 +1,18 @@ true, // Bad - 'posts_per_page' => 999, // Bad - 'posts_per_page' => -1, // Bad - 'posts_per_page' => 1, // OK - 'posts_per_page' => '1', // OK + 'nopaging' => true, // Bad. + 'posts_per_page' => 999, // Bad. + 'posts_per_page' => -1, // Bad. + 'posts_per_page' => 1, // Ok. + 'posts_per_page' => '1', // Ok. ); -_query_posts( 'nopaging=true&posts_per_page=999' ); // Bad +_query_posts( 'nopaging=true&posts_per_page=999' ); // Bad. -$query_args['posts_per_page'] = -1; // Bad -$query_args['posts_per_page'] = 1; // OK -$query_args['posts_per_page'] = '1'; // OK -$query_args['posts_per_page'] = '-1'; // Bad +$query_args['posts_per_page'] = -1; // Bad. +$query_args['posts_per_page'] = 1; // Ok. +$query_args['posts_per_page'] = '1'; // Ok. +$query_args['posts_per_page'] = '-1'; // Bad. -$query_args['my_posts_per_page'] = -1; // OK +$query_args['my_posts_per_page'] = -1; // Ok. diff --git a/WordPress/Tests/VIP/PostsPerPageUnitTest.php b/WordPress/Tests/VIP/PostsPerPageUnitTest.php index 3567484208..5dfb472a00 100644 --- a/WordPress/Tests/VIP/PostsPerPageUnitTest.php +++ b/WordPress/Tests/VIP/PostsPerPageUnitTest.php @@ -1,51 +1,45 @@ + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ -class WordPress_Tests_VIP_PostsPerPageUnitTest extends AbstractSniffUnitTest -{ - /** - * Returns the lines where errors should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of errors that should occur on that line. - * - * @return array(int => int) - */ - public function getErrorList() - { - return array( - 4 => 1, - 5 => 1, - 6 => 1, - 11 => 2, - 13 => 1, - 16 => 1, - ); - - }//end getErrorList() +/** + * Unit test class for the PostsPerPage sniff. + * + * @package WPCS\WordPressCodingStandards + * @since 0.3.0 + */ +class WordPress_Tests_VIP_PostsPerPageUnitTest extends AbstractSniffUnitTest { + /** + * Returns the lines where errors should occur. + * + * @return array => + */ + public function getErrorList() { + return array( + 4 => 1, + 5 => 1, + 6 => 1, + 11 => 2, + 13 => 1, + 16 => 1, + ); - /** - * Returns the lines where warnings should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) - */ - public function getWarningList() - { - return array( - ); + } - }//end getWarningList() + /** + * Returns the lines where warnings should occur. + * + * @return array => + */ + public function getWarningList() { + return array(); + } -}//end class +} // End class. diff --git a/WordPress/Tests/VIP/RestrictedFunctionsUnitTest.inc b/WordPress/Tests/VIP/RestrictedFunctionsUnitTest.inc index 93d4c66816..4be591b00d 100644 --- a/WordPress/Tests/VIP/RestrictedFunctionsUnitTest.inc +++ b/WordPress/Tests/VIP/RestrictedFunctionsUnitTest.inc @@ -1,72 +1,105 @@ 1 ) ); // bad +// Empty line - function moved to another sniff. -add_role( 'test' ); // bad +add_role( 'test' ); // Bad. -array_pop( $array ); // ok +array_pop( $array ); // Ok. class Foo { - function add_role() {} // ok + function add_role() {} // Ok. } class Bar { - static function add_role() {} // ok + static function add_role() {} // Ok. } $x = new Foo(); -$x->add_role(); // ok -$y = Bar::add_role(); // ok -\SomeNamespace\add_role(); // ok - -\add_role(); // bad - -get_term_link( $term ); // bad - -get_page_by_path( $path ); // bad - -get_page_by_title( $page_title ); // bad - -get_term_by( $field, $value, $taxonomy ); // bad - -get_category_by_slug( $slug ); // bad - -url_to_postid( $url ); // bad - -attachment_url_to_postid( $url ); // bad -wpcom_vip_attachment_url_to_postid( $url ); // ok - -get_tag_link(); // error -get_category_link(); // error -get_cat_ID(); // error -url_to_post_id(); // error -attachment_url_to_postid(); // error -get_posts(); // warning -wp_get_recent_posts(); // warning -get_pages(); // error -get_children(); // error -wp_get_post_terms(); // error -wp_get_post_categories(); // error -wp_get_post_tags(); // error -wp_get_object_terms(); // error -term_exists(); // error -count_user_posts(); // error -wp_old_slug_redirect(); // error -get_adjacent_post(); // error -get_previous_post(); // error -get_next_post(); // error -parse_url( 'http://example.com/' ); // warning +$x->add_role(); // Ok. +$y = Bar::add_role(); // Ok. +\SomeNamespace\add_role(); // Ok. + +\add_role(); // Bad. + +get_term_link( $term ); // Bad. + +get_page_by_path( $path ); // Bad. + +get_page_by_title( $page_title ); // Bad. + +get_term_by( $field, $value, $taxonomy ); // Bad. + +get_category_by_slug( $slug ); // Bad. + +url_to_postid( $url ); // Bad. + +attachment_url_to_postid( $url ); // Bad. +wpcom_vip_attachment_url_to_postid( $url ); // Ok. + +get_tag_link(); // Error. +get_category_link(); // Error. +get_cat_ID(); // Error. +url_to_post_id(); // Error. +attachment_url_to_postid(); // Error. +get_posts(); // Warning. +wp_get_recent_posts(); // Warning. + +get_children(); // Warning. +wp_get_post_terms(); // Error. +wp_get_post_categories(); // Error. +wp_get_post_tags(); // Error. +wp_get_object_terms(); // Error. +term_exists(); // Error. +count_user_posts(); // Error. +wp_old_slug_redirect(); // Error. +get_adjacent_post(); // Error. +get_previous_post(); // Error. +get_next_post(); // Error. +parse_url( 'http://example.com/' ); // Warning. + +dl(); // Error. +error_reporting(); // Error. +ini_alter(); // Error. +ini_restore(); // Error. +ini_set(); // Error. +magic_quotes_runtime(); // Error. +set_magic_quotes_runtime(); // Error. +apache_setenv(); // Error. +putenv(); // Error. +set_include_path(); // Error. +restore_include_path(); // Error. +phpinfo(); // Error. + +PHPINFO(); // Error. +CURL_getinfo(); // Error. + +curlyhair(); // Ok. + +get_previous_post_link(); // Error. +get_next_post_link(); // Error. +get_intermediate_image_sizes(); // Error. +serialize(); // Warning. +unserialize(); // Warning. +error_log(); // Error. +var_dump(); // Error. +print_r(); // Error. +trigger_error(); // Error. +set_error_handler(); // Error. +wp_redirect(); // Warning. +wp_is_mobile(); // Error. +urlencode(); // Warning. +rawurlencode(); // Ok. diff --git a/WordPress/Tests/VIP/RestrictedFunctionsUnitTest.php b/WordPress/Tests/VIP/RestrictedFunctionsUnitTest.php index a1778c1a8e..d89f44f39e 100644 --- a/WordPress/Tests/VIP/RestrictedFunctionsUnitTest.php +++ b/WordPress/Tests/VIP/RestrictedFunctionsUnitTest.php @@ -1,89 +1,104 @@ - * @author Greg Sherwood - * @author Marc McIntyre - * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence - * @version Release: @package_version@ - * @link http://pear.php.net/package/PHP_CodeSniffer + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ -class WordPress_Tests_VIP_RestrictedFunctionsUnitTest extends AbstractSniffUnitTest -{ - /** - * Returns the lines where errors should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of errors that should occur on that line. - * - * @return array(int => int) - */ - public function getErrorList() - { - return array( - 3 => 1, - 5 => 1, - 21 => 1, - 34 => version_compare( PHP_VERSION, '5.3.0', '>=' ) ? 0 : 1, - 36 => 1, - 38 => 1, - 40 => 1, - 42 => 1, - 44 => 1, - 46 => 1, - 48 => 1, - 50 => 1, - 53 => 1, - 54 => 1, - 55 => 1, - 56 => 1, - 57 => 1, - 60 => 1, - 61 => 1, - 62 => 1, - 63 => 1, - 64 => 1, - 65 => 1, - 66 => 1, - 67 => 1, - 68 => 1, - 69 => 1, - 70 => 1, - 71 => 1, - ); - - }//end getErrorList() +/** + * Unit test class for the VIP_RestrictedFunctions sniff. + * + * @package WPCS\WordPressCodingStandards + * @since 0.3.0 + */ +class WordPress_Tests_VIP_RestrictedFunctionsUnitTest extends AbstractSniffUnitTest { + /** + * Returns the lines where errors should occur. + * + * @return array => + */ + public function getErrorList() { + return array( + 3 => 1, + 5 => 1, + 21 => 1, + 34 => version_compare( PHP_VERSION, '5.3.0', '>=' ) ? 0 : 1, + 36 => 1, + 38 => 1, + 40 => 1, + 42 => 1, + 44 => 1, + 46 => 1, + 48 => 1, + 50 => 1, + 53 => 1, + 54 => 1, + 55 => 1, + 56 => 1, + 57 => 1, + 62 => 1, + 63 => 1, + 64 => 1, + 65 => 1, + 66 => 1, + 67 => 1, + 68 => 1, + 69 => 1, + 70 => 1, + 71 => 1, + 74 => 1, + 75 => 2, + 76 => 1, + 77 => 1, + 78 => 1, + 79 => 1, + 80 => 1, + 81 => 1, + 82 => 1, + 83 => 1, + 84 => 1, + 85 => 1, + 87 => 1, + 92 => 1, + 93 => 1, + 94 => 1, + 97 => 1, + 98 => 1, + 99 => 1, + 100 => 1, + 101 => 1, + 103 => 1, + ); - /** - * Returns the lines where warnings should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) - */ - public function getWarningList() - { - return array( - 7 => 1, - 9 => 1, - 11 => 1, - 13 => 1, - 15 => 1, - 17 => 1, - 19 => 1, - 58 => 1, - 59 => 1, - 72 => 1, - ); + } // end getErrorList() - }//end getWarningList() + /** + * Returns the lines where warnings should occur. + * + * @return array => + */ + public function getWarningList() { + return array( + 7 => 1, + 9 => 1, + 11 => 1, + 13 => 1, + 15 => 1, + 17 => 1, + 58 => 1, + 59 => 1, + 61 => 1, + 72 => 1, + 88 => 1, + 95 => 1, + 96 => 1, + 102 => 1, + 104 => 1, + ); + } -}//end class +} // End class. diff --git a/WordPress/Tests/VIP/RestrictedVariablesUnitTest.inc b/WordPress/Tests/VIP/RestrictedVariablesUnitTest.inc index 4c6d513f2a..61e919117e 100644 --- a/WordPress/Tests/VIP/RestrictedVariablesUnitTest.inc +++ b/WordPress/Tests/VIP/RestrictedVariablesUnitTest.inc @@ -1,19 +1,19 @@ users"; // bad +$query = "SELECT * FROM $wpdb->users"; // Bad. -$wp_db->update( $wpdb->users, array( 'displayname' => 'Kanobe!' ), array( 'ID' => 1 ) ); // bad +$wp_db->update( $wpdb->users, array( 'displayname' => 'Kanobe!' ), array( 'ID' => 1 ) ); // Bad. -$query = "SELECT * FROM $wpdb->usermeta"; // bad +$query = "SELECT * FROM $wpdb->usermeta"; // Bad. -$wp_db->update( $wpdb->usermeta, array( 'meta_value' => 'bar!' ), array( 'user_id' => 1, 'meta_key' => 'foo' ) ); // bad +$wp_db->update( $wpdb->usermeta, array( 'meta_value' => 'bar!' ), array( 'user_id' => 1, 'meta_key' => 'foo' ) ); // Bad. -$query = "SELECT * FROM $wpdb->posts"; // ok +$query = "SELECT * FROM $wpdb->posts"; // Ok. -if ( isset( $_SERVER['REMOTE_ADDR'] ) ) { // bad - foo( $_SERVER['HTTP_USER_AGENT'] ); // bad +if ( isset( $_SERVER['REMOTE_ADDR'] ) ) { // Bad. + foo( $_SERVER['HTTP_USER_AGENT'] ); // Bad. } -$x = $_COOKIE['bar']; // bad +$x = $_COOKIE['bar']; // Bad. -$y = $_SERVER['REQUEST_URI']; // ok +$y = $_SERVER['REQUEST_URI']; // Ok. diff --git a/WordPress/Tests/VIP/RestrictedVariablesUnitTest.php b/WordPress/Tests/VIP/RestrictedVariablesUnitTest.php index ef03c83449..b7d0e0b6b2 100644 --- a/WordPress/Tests/VIP/RestrictedVariablesUnitTest.php +++ b/WordPress/Tests/VIP/RestrictedVariablesUnitTest.php @@ -1,59 +1,47 @@ - * @author Greg Sherwood - * @author Marc McIntyre - * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence - * @version Release: @package_version@ - * @link http://pear.php.net/package/PHP_CodeSniffer + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ -class WordPress_Tests_VIP_RestrictedVariablesUnitTest extends AbstractSniffUnitTest -{ +/** + * Unit test class for the VIP_RestrictedVariables sniff. + * + * @package WPCS\WordPressCodingStandards + * @since 0.3.0 + */ +class WordPress_Tests_VIP_RestrictedVariablesUnitTest extends AbstractSniffUnitTest { /** * Returns the lines where errors should occur. * - * The key of the array should represent the line number and the value - * should represent the number of errors that should occur on that line. - * - * @return array(int => int) + * @return array => */ - public function getErrorList() - { + public function getErrorList() { return array( 3 => 1, 5 => 1, 7 => 1, 9 => 1, - ); - - }//end getErrorList() + ); + } /** * Returns the lines where warnings should occur. * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) + * @return array => */ - public function getWarningList() - { + public function getWarningList() { return array( 13 => 1, 14 => 1, 17 => 1, - ); - - }//end getWarningList() - + ); -}//end class + } +} // End class. diff --git a/WordPress/Tests/VIP/SessionFunctionsUsageUnitTest.php b/WordPress/Tests/VIP/SessionFunctionsUsageUnitTest.php index 05737d9523..0f2c70fd07 100644 --- a/WordPress/Tests/VIP/SessionFunctionsUsageUnitTest.php +++ b/WordPress/Tests/VIP/SessionFunctionsUsageUnitTest.php @@ -1,51 +1,40 @@ - * @link http://pear.php.net/package/PHP_CodeSniffer + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ -class WordPress_Tests_VIP_SessionFunctionsUsageUnitTest extends AbstractSniffUnitTest -{ - +/** + * Unit test class for the SessionFunctionsUsage sniff. + * + * @package WPCS\WordPressCodingStandards + * @since 0.3.0 + */ +class WordPress_Tests_VIP_SessionFunctionsUsageUnitTest extends AbstractSniffUnitTest { /** * Returns the lines where errors should occur. * - * The key of the array should represent the line number and the value - * should represent the number of errors that should occur on that line. - * - * @return array(int => int) + * @return array => */ - public function getErrorList() - { + public function getErrorList() { return array( 3 => 1, - ); - - }//end getErrorList() + ); + } /** * Returns the lines where warnings should occur. * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) + * @return array => */ - public function getWarningList() - { + public function getWarningList() { return array(); - }//end getWarningList() - - -}//end class + } -?> +} // End class. diff --git a/WordPress/Tests/VIP/SessionVariableUsageUnitTest.php b/WordPress/Tests/VIP/SessionVariableUsageUnitTest.php index e4737f31f9..102afe5a54 100644 --- a/WordPress/Tests/VIP/SessionVariableUsageUnitTest.php +++ b/WordPress/Tests/VIP/SessionVariableUsageUnitTest.php @@ -1,52 +1,41 @@ - * @link http://pear.php.net/package/PHP_CodeSniffer + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ -class WordPress_Tests_VIP_SessionVariableUsageUnitTest extends AbstractSniffUnitTest -{ - +/** + * Unit test class for the SessionVariableUsage sniff. + * + * @package WPCS\WordPressCodingStandards + * @since 0.3.0 + */ +class WordPress_Tests_VIP_SessionVariableUsageUnitTest extends AbstractSniffUnitTest { /** * Returns the lines where errors should occur. * - * The key of the array should represent the line number and the value - * should represent the number of errors that should occur on that line. - * - * @return array(int => int) + * @return array => */ - public function getErrorList() - { + public function getErrorList() { return array( 3 => 1, 4 => 1, - ); - - }//end getErrorList() + ); + } /** * Returns the lines where warnings should occur. * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) + * @return array => */ - public function getWarningList() - { + public function getWarningList() { return array(); - }//end getWarningList() - - -}//end class + } -?> +} // End class. diff --git a/WordPress/Tests/VIP/SlowDBQueryUnitTest.inc b/WordPress/Tests/VIP/SlowDBQueryUnitTest.inc index 3d0857780f..cf40bacb62 100644 --- a/WordPress/Tests/VIP/SlowDBQueryUnitTest.inc +++ b/WordPress/Tests/VIP/SlowDBQueryUnitTest.inc @@ -5,19 +5,35 @@ new WP_Query( array( array( 'key' => 'foo', 'value' => 'bar', - ), ), + ), 'tax_query' => array( array( 'taxonomy' => 'foo', - ), ), + ), 'meta_key' => 'foo', 'meta_value' => 'bar', - ) ); +) ); $query = 'foo=bar&meta_key=foo&meta_value=bar'; if ( ! isset( $widget['params'][0] ) ) { $widget['params'][0] = array(); } + + +// Testing whitelisting comments. +$test = array( + + // Single-line statements. + 'tax_query' => array(), // Bad. + 'tax_query' => array(), // WPCS: tax_query ok. + + // Multi-line statement. + 'tax_query' => array( // WPCS: tax_query ok. + array( + 'taxonomy' => 'foo', + ), + ), +); diff --git a/WordPress/Tests/VIP/SlowDBQueryUnitTest.php b/WordPress/Tests/VIP/SlowDBQueryUnitTest.php index 74b5755dd2..57a0c4b5e8 100644 --- a/WordPress/Tests/VIP/SlowDBQueryUnitTest.php +++ b/WordPress/Tests/VIP/SlowDBQueryUnitTest.php @@ -1,52 +1,45 @@ + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ -class WordPress_Tests_VIP_SlowDBQueryUnitTest extends AbstractSniffUnitTest -{ - /** - * Returns the lines where errors should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of errors that should occur on that line. - * - * @return array(int => int) - */ - public function getErrorList() - { - return array( - ); - - }//end getErrorList() - - - /** - * Returns the lines where warnings should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) - */ - public function getWarningList() - { - return array( - 4 => 1, - 10 => 1, - 15 => 1, - 16 => 1, - 19 => 2, - ); - - }//end getWarningList() - - -}//end class - -?> +/** + * Unit test class for the SlowDBQuery sniff. + * + * @package WPCS\WordPressCodingStandards + * @since 0.3.0 + */ +class WordPress_Tests_VIP_SlowDBQueryUnitTest extends AbstractSniffUnitTest { + + /** + * Returns the lines where errors should occur. + * + * @return array => + */ + public function getErrorList() { + return array(); + + } + + /** + * Returns the lines where warnings should occur. + * + * @return array => + */ + public function getWarningList() { + return array( + 4 => 1, + 10 => 1, + 15 => 1, + 16 => 1, + 19 => 2, + 30 => 1, + ); + + } + +} // End class. diff --git a/WordPress/Tests/VIP/SuperGlobalInputUsageUnitTest.inc b/WordPress/Tests/VIP/SuperGlobalInputUsageUnitTest.inc index 36079061e5..ecb1315625 100644 --- a/WordPress/Tests/VIP/SuperGlobalInputUsageUnitTest.inc +++ b/WordPress/Tests/VIP/SuperGlobalInputUsageUnitTest.inc @@ -2,14 +2,19 @@ foo( $_GET['bar'] ); -foo( $_GET['whitelisted'] ); // input var okay +foo( $_GET['whitelisted'] ); // Input var okay. + +foo( $_POST['whitelisted_with_prefix'] ); // WPCS: input var okay. if ( $_GET['test'] && foo() && $bar ) { // input var okay taz(); } -bar( $_POST['foo'] ); // warning +bar( $_POST['foo'] ); // Warning. + +quux( $_REQUEST['quux'] ); // Warning. -quux( $_REQUEST['quux'] ); // warning +$_REQUEST['wp_customize'] = 'on'; // Ok. -$_REQUEST['wp_customize'] = 'on'; // ok +// Issue: https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards/issues/542 +if ( isset( $_GET['updated'] ) ) { // input var okay ?> diff --git a/WordPress/Tests/VIP/SuperGlobalInputUsageUnitTest.php b/WordPress/Tests/VIP/SuperGlobalInputUsageUnitTest.php index d1adf8f119..f5df99fabc 100644 --- a/WordPress/Tests/VIP/SuperGlobalInputUsageUnitTest.php +++ b/WordPress/Tests/VIP/SuperGlobalInputUsageUnitTest.php @@ -1,53 +1,41 @@ - * @link http://pear.php.net/package/PHP_CodeSniffer + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ -class WordPress_Tests_VIP_SuperGlobalInputUsageUnitTest extends AbstractSniffUnitTest -{ - +/** + * Unit test class for the SuperGlobalInputUsage sniff. + * + * @package WPCS\WordPressCodingStandards + * @since 0.3.0 + */ +class WordPress_Tests_VIP_SuperGlobalInputUsageUnitTest extends AbstractSniffUnitTest { /** * Returns the lines where errors should occur. * - * The key of the array should represent the line number and the value - * should represent the number of errors that should occur on that line. - * - * @return array(int => int) + * @return array => */ - public function getErrorList() - { - return array( - ); - - }//end getErrorList() + public function getErrorList() { + return array(); + } /** * Returns the lines where warnings should occur. * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) + * @return array => */ - public function getWarningList() - { + public function getWarningList() { return array( 3 => 1, - 11 => 1, 13 => 1, - ); - - }//end getWarningList() - - -}//end class + 15 => 1, + ); + } +} // End class. diff --git a/WordPress/Tests/VIP/TimezoneChangeUnitTest.inc b/WordPress/Tests/VIP/TimezoneChangeUnitTest.inc index f0de5d8c4f..4e38791f9b 100644 --- a/WordPress/Tests/VIP/TimezoneChangeUnitTest.inc +++ b/WordPress/Tests/VIP/TimezoneChangeUnitTest.inc @@ -1,6 +1,6 @@ setTimezone( new DateTimeZone( 'America/Toronto' ) ); // Yay! diff --git a/WordPress/Tests/VIP/TimezoneChangeUnitTest.php b/WordPress/Tests/VIP/TimezoneChangeUnitTest.php index 24569b1a7e..a88b4923b4 100644 --- a/WordPress/Tests/VIP/TimezoneChangeUnitTest.php +++ b/WordPress/Tests/VIP/TimezoneChangeUnitTest.php @@ -1,51 +1,40 @@ - * @link http://pear.php.net/package/PHP_CodeSniffer + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ -class WordPress_Tests_VIP_TimezoneChangeUnitTest extends AbstractSniffUnitTest -{ - +/** + * Unit test class for the TimezoneChange sniff. + * + * @package WPCS\WordPressCodingStandards + * @since 0.3.0 + */ +class WordPress_Tests_VIP_TimezoneChangeUnitTest extends AbstractSniffUnitTest { /** * Returns the lines where errors should occur. * - * The key of the array should represent the line number and the value - * should represent the number of errors that should occur on that line. - * - * @return array(int => int) + * @return array => */ - public function getErrorList() - { + public function getErrorList() { return array( 3 => 1, - ); - - }//end getErrorList() + ); + } /** * Returns the lines where warnings should occur. * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) + * @return array => */ - public function getWarningList() - { + public function getWarningList() { return array(); - }//end getWarningList() - - -}//end class + } -?> +} // End class. diff --git a/WordPress/Tests/VIP/ValidatedSanitizedInputUnitTest.inc b/WordPress/Tests/VIP/ValidatedSanitizedInputUnitTest.inc index 4659c0e39c..0249040471 100644 --- a/WordPress/Tests/VIP/ValidatedSanitizedInputUnitTest.inc +++ b/WordPress/Tests/VIP/ValidatedSanitizedInputUnitTest.inc @@ -1,13 +1,13 @@ $value ) { // .. } -unset( $_GET['test'] ); // ok +unset( $_GET['test'] ); // Ok. -output( "some string {$_POST['some_var']}" ); // Bad +output( "some string {$_POST['some_var']}" ); // Bad. -echo (int) $_GET['test']; // ok -some_func( $some_arg, (int) $_GET['test'] ); // ok +echo (int) $_GET['test']; // Ok. +some_func( $some_arg, (int) $_GET['test'] ); // Ok. function zebra() { if ( isset( $_GET['foo'], $_POST['bar'] ) ) { - echo sanitize_text_field( wp_unslash( $_POST['bar'] ) ); // ok + echo sanitize_text_field( wp_unslash( $_POST['bar'] ) ); // Ok. } } echo $_GET['test']; // WPCS: sanitization OK. -echo array_map( 'sanitize_text_field', wp_unslash( $_GET['test'] ) ); // OK -echo array_map( 'foo', wp_unslash( $_GET['test'] ) ); // Bad -echo array_map( $something, wp_unslash( $_GET['test'] ) ); // Bad -echo array_map( array( $obj, 'func' ), wp_unslash( $_GET['test'] ) ); // Bad -echo array_map( array( $obj, 'sanitize_text_field' ), wp_unslash( $_GET['test'] ) ); // Bad +echo array_map( 'sanitize_text_field', wp_unslash( $_GET['test'] ) ); // Ok. +echo array_map( 'foo', wp_unslash( $_GET['test'] ) ); // Bad. +echo array_map( $something, wp_unslash( $_GET['test'] ) ); // Bad. +echo array_map( array( $obj, 'func' ), wp_unslash( $_GET['test'] ) ); // Bad. +echo array_map( array( $obj, 'sanitize_text_field' ), wp_unslash( $_GET['test'] ) ); // Bad. // Sanitized but not validated. -$foo = (int) $_POST['foo6']; // Bad +$foo = (int) $_POST['foo6']; // Bad. // Non-assignment checks are OK. -if ( 'bar' === $_POST['foo'] ) {} // OK -if ( $_GET['test'] != 'a' ) {} // OK -if ( 'bar' === do_something( wp_unslash( $_POST['foo'] ) ) ) {} // Bad +if ( 'bar' === $_POST['foo'] ) {} // Ok. +if ( $_GET['test'] != 'a' ) {} // Ok. +if ( 'bar' === do_something( wp_unslash( $_POST['foo'] ) ) ) {} // Bad. -switch ( $_POST['foo'] ) {} // OK -switch ( do_something( wp_unslash( $_POST['foo'] ) ) ) {} // Bad +switch ( $_POST['foo'] ) {} // Ok. +switch ( do_something( wp_unslash( $_POST['foo'] ) ) ) {} // Bad. // Sanitization is required even when the value is being escaped. -echo esc_html( wp_unslash( $_POST['foo'] ) ); // Bad -echo esc_html( sanitize_text_field( wp_unslash( $_POST['foo'] ) ) ); // OK +echo esc_html( wp_unslash( $_POST['foo'] ) ); // Bad. +echo esc_html( sanitize_text_field( wp_unslash( $_POST['foo'] ) ) ); // Ok. -$current_tax_slug = isset( $_GET['a'] ) ? sanitize_key( $_GET['a'] ) : false; // OK +$current_tax_slug = isset( $_GET['a'] ) ? sanitize_key( $_GET['a'] ) : false; // Ok. $current_tax_slug = isset( $_GET['a'] ) ? $_GET['a'] : false; // Bad x 2 -$current_tax_slug = isset( $_GET['a'] ) ? wp_unslash( $_GET['a'] ) : false; // Bad -$current_tax_slug = isset( $_GET['a'] ) ? sanitize_text_field( wp_unslash( $_GET['a'] ) ) : false; // OK +$current_tax_slug = isset( $_GET['a'] ) ? wp_unslash( $_GET['a'] ) : false; // Bad. +$current_tax_slug = isset( $_GET['a'] ) ? sanitize_text_field( wp_unslash( $_GET['a'] ) ) : false; // Ok. -echo sanitize_text_field( $_POST['foo545'] ); // Error for no validation, unslashing -echo array_map( 'sanitize_text_field', $_GET['test'] ); // Bad, no unslashing -echo array_map( 'sanitize_key', $_GET['test'] ); // OK +echo sanitize_text_field( $_POST['foo545'] ); // Error for no validation, unslashing. +echo array_map( 'sanitize_text_field', $_GET['test'] ); // Bad, no unslashing. +echo array_map( 'sanitize_key', $_GET['test'] ); // Ok. -foo( absint( $_GET['foo'] ) ); // OK -$ids = array_map( 'absint', $_GET['test'] ); // OK +foo( absint( $_GET['foo'] ) ); // Ok. +$ids = array_map( 'absint', $_GET['test'] ); // Ok. -if ( is_array( $_GET['test'] ) ) {} // OK +if ( is_array( $_GET['test'] ) ) {} // Ok. -output( "some string \$_POST[some_var]" ); // Ok -output( "some string \\$_POST[some_var] $_GET[evil]" ); // Bad 2 +output( "some string \$_POST[some_var]" ); // Ok. +output( "some string \\$_POST[some_var] $_GET[evil]" ); // Bad x2. diff --git a/WordPress/Tests/VIP/ValidatedSanitizedInputUnitTest.php b/WordPress/Tests/VIP/ValidatedSanitizedInputUnitTest.php index 89625dcd11..9b9cc8f113 100644 --- a/WordPress/Tests/VIP/ValidatedSanitizedInputUnitTest.php +++ b/WordPress/Tests/VIP/ValidatedSanitizedInputUnitTest.php @@ -1,29 +1,26 @@ - * @link http://pear.php.net/package/PHP_CodeSniffer + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ -class WordPress_Tests_VIP_ValidatedSanitizedInputUnitTest extends AbstractSniffUnitTest -{ - +/** + * Unit test class for the ValidatedSanitizedInput sniff. + * + * @package WPCS\WordPressCodingStandards + * @since 0.3.0 + */ +class WordPress_Tests_VIP_ValidatedSanitizedInputUnitTest extends AbstractSniffUnitTest { /** * Returns the lines where errors should occur. * - * The key of the array should represent the line number and the value - * should represent the number of errors that should occur on that line. - * - * @return array(int => int) + * @return array => */ - public function getErrorList() - { + public function getErrorList() { return array( 5 => 3, 7 => 1, @@ -44,26 +41,18 @@ public function getErrorList() 104 => 2, 105 => 1, 114 => 2, - ); - - }//end getErrorList() + ); + } /** * Returns the lines where warnings should occur. * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) + * @return array => */ - public function getWarningList() - { + public function getWarningList() { return array(); - }//end getWarningList() - - -}//end class + } -?> +} // End class. diff --git a/WordPress/Tests/Variables/GlobalVariablesUnitTest.inc b/WordPress/Tests/Variables/GlobalVariablesUnitTest.inc index 30e3cd8310..4535a7bcc1 100644 --- a/WordPress/Tests/Variables/GlobalVariablesUnitTest.inc +++ b/WordPress/Tests/Variables/GlobalVariablesUnitTest.inc @@ -6,4 +6,4 @@ global $wpdb; $wpdb = 'test'; global $post; -$post = get_post( 1 ); // override ok \ No newline at end of file +$post = get_post( 1 ); // Override ok. \ No newline at end of file diff --git a/WordPress/Tests/Variables/GlobalVariablesUnitTest.php b/WordPress/Tests/Variables/GlobalVariablesUnitTest.php index efb8e0ee70..dee8ca0fcf 100644 --- a/WordPress/Tests/Variables/GlobalVariablesUnitTest.php +++ b/WordPress/Tests/Variables/GlobalVariablesUnitTest.php @@ -1,48 +1,41 @@ + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ -class WordPress_Tests_Variables_GlobalVariablesUnitTest extends AbstractSniffUnitTest -{ + +/** + * Unit test class for the GlobalVariables sniff. + * + * @package WPCS\WordPressCodingStandards + * @since 0.3.0 + */ +class WordPress_Tests_Variables_GlobalVariablesUnitTest extends AbstractSniffUnitTest { /** * Returns the lines where errors should occur. * - * The key of the array should represent the line number and the value - * should represent the number of errors that should occur on that line. - * - * @return array(int => int) + * @return array => */ - public function getErrorList() - { + public function getErrorList() { return array( 3 => 1, 6 => 1, ); - - }//end getErrorList() - + } /** * Returns the lines where warnings should occur. * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) + * @return array => */ - public function getWarningList() - { - return array( - ); - - }//end getWarningList() + public function getWarningList() { + return array(); + } -}//end class +} // End class. diff --git a/WordPress/Tests/Variables/VariableRestrictionsUnitTest.inc b/WordPress/Tests/Variables/VariableRestrictionsUnitTest.inc index 1e171ec302..0038124db3 100644 --- a/WordPress/Tests/Variables/VariableRestrictionsUnitTest.inc +++ b/WordPress/Tests/Variables/VariableRestrictionsUnitTest.inc @@ -1,25 +1,25 @@ bar ); // Matches: '$foo->bar' +test( $foo->bar ); // Matches: '$foo->bar'. -$foo->bar(); // Ignored, this is a function not a variable +$foo->bar(); // Ignored, this is a function not a variable. -$foo->bar_method(); // Ignored +$foo->bar_method(); // Ignored. -FOO::var; // Matches: 'FOO::var' +FOO::var; // Matches: 'FOO::var'. FOO::var_test; -FOO::reg; // Matches: 'FOO::reg*' +FOO::reg; // Matches: 'FOO::reg*'. -FOO::regex; // Matches: 'FOO::reg*' +FOO::regex; // Matches: 'FOO::reg*'. -FOO::var(); // Ignored +FOO::var(); // Ignored. -FOO::$static; // Matches: 'FOO::$static' +FOO::$static; // Matches: 'FOO::$static'. -$foo['test']; // Matches: '$foo['test']' +$foo['test']; // Matches: '$foo['test']'. -$foo["test"]; // Matches: '$foo['test']' AND $foo['test'] +$foo["test"]; // Matches: '$foo['test']' AND $foo['test']. diff --git a/WordPress/Tests/Variables/VariableRestrictionsUnitTest.php b/WordPress/Tests/Variables/VariableRestrictionsUnitTest.php index 3484039be9..9684a9a819 100644 --- a/WordPress/Tests/Variables/VariableRestrictionsUnitTest.php +++ b/WordPress/Tests/Variables/VariableRestrictionsUnitTest.php @@ -1,76 +1,72 @@ + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ -class WordPress_Tests_Variables_VariableRestrictionsUnitTest extends AbstractSniffUnitTest -{ +/** + * Unit test class for the VariableRestrictions sniff. + * + * @package WPCS\WordPressCodingStandards + * @since 0.3.0 + */ +class WordPress_Tests_Variables_VariableRestrictionsUnitTest extends AbstractSniffUnitTest { + + /** + * Fill in the $groups property to test the abstract class. + */ protected function setUp() { parent::setUp(); - WordPress_Sniffs_Variables_VariableRestrictionsSniff::$groups = array( + WordPress_AbstractVariableRestrictionsSniff::$groups = array( 'test' => array( - 'type' => 'error', - 'message' => 'Detected usage of %s', - 'object_vars' => array( + 'type' => 'error', + 'message' => 'Detected usage of %s', + 'object_vars' => array( '$foo->bar', 'FOO::var', 'FOO::reg*', 'FOO::$static', - ), + ), 'array_members' => array( '$foo[\'test\']', - ), - 'variables' => array( + ), + 'variables' => array( '$taz', - ), - ), - ); + ), + ); } - /** - * Returns the lines where errors should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of errors that should occur on that line. - * - * @return array(int => int) - */ - public function getErrorList() - { - return array( - 3 => 1, - 5 => 1, - 11 => 1, - 15 => 1, - 17 => 1, - 21 => 1, - 23 => 1, - ); - - }//end getErrorList() - + /** + * Returns the lines where errors should occur. + * + * @return array => + */ + public function getErrorList() { + return array( + 3 => 1, + 5 => 1, + 11 => 1, + 15 => 1, + 17 => 1, + 21 => 1, + 23 => 1, + ); - /** - * Returns the lines where warnings should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) - */ - public function getWarningList() - { - return array( - ); + } - }//end getWarningList() + /** + * Returns the lines where warnings should occur. + * + * @return array => + */ + public function getWarningList() { + return array(); + } -}//end class +} // End class. diff --git a/WordPress/Tests/WP/EnqueuedResourcesUnitTest.php b/WordPress/Tests/WP/EnqueuedResourcesUnitTest.php index c63f33c46c..31255edea5 100644 --- a/WordPress/Tests/WP/EnqueuedResourcesUnitTest.php +++ b/WordPress/Tests/WP/EnqueuedResourcesUnitTest.php @@ -1,62 +1,56 @@ + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ -class WordPress_Tests_WP_EnqueuedResourcesUnitTest extends AbstractSniffUnitTest -{ - - /** - * Skip this test on PHP 5.2. - * - * @since 0.9.0 - * - * @return bool Whether to skip this test. - */ - protected function shouldSkipTest() { - return version_compare( PHP_VERSION, '5.3.0', '<' ); - } - - /** - * Returns the lines where errors should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of errors that should occur on that line. - * - * @return array(int => int) - */ - public function getErrorList() - { - return array( - 1 => 1, - 2 => 1, - 6 => 1, - 7 => 1, - 10 => 1, - 11 => 1, - ); - - }//end getErrorList() - - - /** - * Returns the lines where warnings should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) - */ - public function getWarningList() - { - return array(); - }//end getWarningList() - - -}//end class +/** + * Unit test class for the EnqueuedResources sniff. + * + * @package WPCS\WordPressCodingStandards + * @since 0.3.0 + */ +class WordPress_Tests_WP_EnqueuedResourcesUnitTest extends AbstractSniffUnitTest { + + /** + * Skip this test on PHP 5.2. + * + * @since 0.9.0 + * + * @return bool Whether to skip this test. + */ + protected function shouldSkipTest() { + return version_compare( PHP_VERSION, '5.3.0', '<' ); + } + + /** + * Returns the lines where errors should occur. + * + * @return array => + */ + public function getErrorList() { + return array( + 1 => 1, + 2 => 1, + 6 => 1, + 7 => 1, + 10 => 1, + 11 => 1, + ); + + } + + /** + * Returns the lines where warnings should occur. + * + * @return array => + */ + public function getWarningList() { + return array(); + + } + +} // End class. diff --git a/WordPress/Tests/WP/I18nUnitTest.inc b/WordPress/Tests/WP/I18nUnitTest.inc new file mode 100644 index 0000000000..9743060a06 --- /dev/null +++ b/WordPress/Tests/WP/I18nUnitTest.inc @@ -0,0 +1,108 @@ +setSniffProperty( 'WordPress_Sniffs_WP_I18nSniff', 'text_domain', 'my-slug' ); + WordPress_Sniffs_WP_I18nSniff::$text_domain_override = 'my-slug'; + parent::setUp(); + } + + /** + * Returns the lines where errors should occur. + * + * @return array => + */ + public function getErrorList() { + return array( + 3 => 1, + 6 => 1, + 9 => 1, + 11 => 1, + 13 => 1, + 15 => 1, + 17 => 1, + 19 => 1, + 21 => 1, + 23 => 1, + 25 => 1, + 27 => 1, + 33 => 1, + 35 => 1, + 37 => 1, + 39 => 1, + 41 => 1, + 43 => 1, + 45 => 1, + 47 => 1, + 48 => 1, + 50 => 1, + 52 => 1, + 53 => 1, + 55 => 1, + 56 => 2, + 58 => 1, + 59 => 1, + 60 => 1, + 62 => 1, + 63 => 2, + 65 => 1, + 66 => 1, + 67 => 1, + 72 => 1, + 74 => 1, + 75 => 1, + 76 => 1, + 77 => 1, + 78 => 1, + 93 => 1, + 95 => 2, + 100 => 1, + 101 => 1, + 102 => 1, + 103 => 1, + 105 => 1, + 106 => 1, + 107 => 1, + ); + } // end getErrorList() + + /** + * Returns the lines where warnings should occur. + * + * @return array => + */ + public function getWarningList() { + return array( + 69 => 1, + 70 => 1, + 100 => 1, + 101 => 1, + 102 => 1, + 103 => 1, + ); + } + +} // End class. diff --git a/WordPress/Tests/WP/PreparedSQLUnitTest.inc b/WordPress/Tests/WP/PreparedSQLUnitTest.inc index db3d5289ea..ff20f58be8 100644 --- a/WordPress/Tests/WP/PreparedSQLUnitTest.inc +++ b/WordPress/Tests/WP/PreparedSQLUnitTest.inc @@ -1,26 +1,26 @@ query( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '" . $_GET['title'] . "';" ); // Bad -$wpdb->query( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '{$_GET['title']}';" ); // Bad -$wpdb->query( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '$var';" ); // Bad -$wpdb->query( "SELECT * FROM $wpdb->posts WHERE post_title LIKE 'Hello World!';" ); // OK -$wpdb->query( $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '{$_GET['title']}';" ) ); // Bad -$wpdb->query( $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '$var';" ) ); // Bad -$wpdb->query( $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_title LIKE %s;", $_GET['title'] ) ); // OK +$wpdb->query( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '" . $_GET['title'] . "';" ); // Bad. +$wpdb->query( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '{$_GET['title']}';" ); // Bad. +$wpdb->query( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '$var';" ); // Bad. +$wpdb->query( "SELECT * FROM $wpdb->posts WHERE post_title LIKE 'Hello World!';" ); // Ok. +$wpdb->query( $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '{$_GET['title']}';" ) ); // Bad. +$wpdb->query( $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '$var';" ) ); // Bad. +$wpdb->query( $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_title LIKE %s;", $_GET['title'] ) ); // Ok. $wpdb->query( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '" . $escaped_var . "';" ); // WPCS: unprepared SQL OK. $wpdb->query( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '{$escaped_var}';" ); // WPCS: unprepared SQL OK. -$wpdb->query( $wpdb->prepare( "SELECT SUBSTRING( post_name, %d + 1 ) REGEXP '^[0-9]+$'", array( 123 ) ) ); // OK -$wpdb->query( $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_title = 'The \$_GET var can be evil.' AND ID = %s", array( 123 ) ) ); // OK -$wpdb->query( $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_title = 'The $_GET[foo] var is evil.' AND ID = %s", array( 123 ) ) ); // Bad -$wpdb->query( $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_title = 'The \\$_GET[foo]// var is evil again.' AND ID = %s", array( 123 ) ) ); // Bad -$wpdb->query( $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_title = 'The \$_GET var can be evil, but $_GET[foo] var is evil.' AND ID = %s", array( 123 ) ) ); // Bad +$wpdb->query( $wpdb->prepare( "SELECT SUBSTRING( post_name, %d + 1 ) REGEXP '^[0-9]+$'", array( 123 ) ) ); // Ok. +$wpdb->query( $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_title = 'The \$_GET var can be evil.' AND ID = %s", array( 123 ) ) ); // Ok. +$wpdb->query( $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_title = 'The $_GET[foo] var is evil.' AND ID = %s", array( 123 ) ) ); // Bad. +$wpdb->query( $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_title = 'The \\$_GET[foo]// var is evil again.' AND ID = %s", array( 123 ) ) ); // Bad. +$wpdb->query( $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_title = 'The \$_GET var can be evil, but $_GET[foo] var is evil.' AND ID = %s", array( 123 ) ) ); // Bad. -$wpdb->query( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '" . foo() . "';" ); // Bad -$wpdb->query( $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '" . foo() . "';" ) ); // Bad +$wpdb->query( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '" . foo() . "';" ); // Bad. +$wpdb->query( $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '" . foo() . "';" ) ); // Bad. -$wpdb->query( "SELECT * FROM " . $wpdb->posts . " WHERE post_title LIKE 'foo';" ); // OK +$wpdb->query( "SELECT * FROM " . $wpdb->posts . " WHERE post_title LIKE 'foo';" ); // Ok. // All OK. $all_post_meta = $wpdb->get_results( $wpdb->prepare( sprintf( @@ -29,5 +29,5 @@ $all_post_meta = $wpdb->get_results( $wpdb->prepare( sprintf( implode( ',', array_fill( 0, count( $post_ids ), '%d' ) ) ), $post_ids ) ); -$wpdb->query( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '" . esc_sql( $foo ) . "';" ); // OK -$wpdb->query( "SELECT * FROM $wpdb->posts WHERE ID = " . absint( $foo ) . ";" ); // OK +$wpdb->query( "SELECT * FROM $wpdb->posts WHERE post_title LIKE '" . esc_sql( $foo ) . "';" ); // Ok. +$wpdb->query( "SELECT * FROM $wpdb->posts WHERE ID = " . absint( $foo ) . ";" ); // Ok. diff --git a/WordPress/Tests/WP/PreparedSQLUnitTest.php b/WordPress/Tests/WP/PreparedSQLUnitTest.php index 1786a69dac..6058ae70d0 100644 --- a/WordPress/Tests/WP/PreparedSQLUnitTest.php +++ b/WordPress/Tests/WP/PreparedSQLUnitTest.php @@ -1,20 +1,26 @@ => */ public function getErrorList() { return array( @@ -32,10 +38,15 @@ public function getErrorList() { } /** + * Returns the lines where warnings should occur. + * * @since 0.8.0 + * + * @return array => */ public function getWarningList() { return array(); + } -} // end class. +} // End class. diff --git a/WordPress/Tests/WhiteSpace/CastStructureSpacingUnitTest.inc b/WordPress/Tests/WhiteSpace/CastStructureSpacingUnitTest.inc index 2601356fa2..f718db10e5 100644 --- a/WordPress/Tests/WhiteSpace/CastStructureSpacingUnitTest.inc +++ b/WordPress/Tests/WhiteSpace/CastStructureSpacingUnitTest.inc @@ -7,7 +7,7 @@ $bool1 = (bool)$bool; $bool2 = (bool) $bool; $int1 = (int)$int; -$int2 = (int) $int +$int2 = (int) $int; $obj1 = ( object )$object; $obj2 = (object) $object; diff --git a/WordPress/Tests/WhiteSpace/CastStructureSpacingUnitTest.php b/WordPress/Tests/WhiteSpace/CastStructureSpacingUnitTest.php index 0c3d35d3e8..28bf974b43 100644 --- a/WordPress/Tests/WhiteSpace/CastStructureSpacingUnitTest.php +++ b/WordPress/Tests/WhiteSpace/CastStructureSpacingUnitTest.php @@ -1,71 +1,46 @@ int) - */ - public function getErrorList() - { - return array(); - - }//end getErrorList() - - - /** - * Returns the lines where warnings should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) - */ - public function getWarningList() - { - return array( - 3 => 1, - 6 => 1, - 9 => 1, - 12 => 2, - 15 => 1, - 18 => 1, - 21 => 1, - ); - - }//end getWarningList() - - -}//end class - -?> +class WordPress_Tests_WhiteSpace_CastStructureSpacingUnitTest extends AbstractSniffUnitTest { + + /** + * Returns the lines where errors should occur. + * + * @return array => + */ + public function getErrorList() { + return array(); + + } + + /** + * Returns the lines where warnings should occur. + * + * @return array => + */ + public function getWarningList() { + return array( + 3 => 1, + 6 => 1, + 9 => 1, + 12 => 2, + 15 => 1, + 18 => 1, + 21 => 1, + ); + + } + +} // End class. diff --git a/WordPress/Tests/WhiteSpace/ControlStructureSpacingUnitTest.inc b/WordPress/Tests/WhiteSpace/ControlStructureSpacingUnitTest.inc index 79a5b286d4..e5216cb8c8 100644 --- a/WordPress/Tests/WhiteSpace/ControlStructureSpacingUnitTest.inc +++ b/WordPress/Tests/WhiteSpace/ControlStructureSpacingUnitTest.inc @@ -1,31 +1,31 @@ - * @author Greg Sherwood - * @author Marc McIntyre - * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence - * @link http://pear.php.net/package/PHP_CodeSniffer + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ /** * Unit test class for the ControlStructureSpacing sniff. * - * A sniff unit test checks a .inc file for expected violations of a single - * coding standard. Expected errors and warnings are stored in this class. - * - * @category PHP - * @package PHP_CodeSniffer - * @author Akeda Bagus - * @author Greg Sherwood - * @author Marc McIntyre - * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence - * @version Release: @package_version@ - * @link http://pear.php.net/package/PHP_CodeSniffer + * @package WPCS\WordPressCodingStandards + * @since 2013-06-11 */ -class WordPress_Tests_WhiteSpace_ControlStructureSpacingUnitTest extends AbstractSniffUnitTest -{ - - /** - * Skip this test on PHP 5.2. - * - * @since 0.9.0 - * - * @return bool Whether to skip this test. - */ - protected function shouldSkipTest() { - return version_compare( PHP_VERSION, '5.3.0', '<' ); - } - - /** - * Returns the lines where errors should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of errors that should occur on that line. - * - * @return array(int => int) - */ - public function getErrorList() - { - $ret = array( - 4 => 2, - 17 => 2, - 29 => 5, - 37 => 1, - 41 => 1, - 42 => 1, - 49 => 5, - 58 => 3, - 67 => 1, - 68 => 1, - 69 => 1, - 71 => 1, - 72 => 1, - 81 => 3, - 82 => 1, - 85 => 1, - 91 => 2, - 92 => 1, - 94 => 1, - 95 => 1, - 97 => 1, - 98 => 1, - ); +class WordPress_Tests_WhiteSpace_ControlStructureSpacingUnitTest extends AbstractSniffUnitTest { - // Uncomment when "$blank_line_check" parameter will be "true" by default. - /*$ret[29] += 1; - $ret[33] = 1; - $ret[36] = 1; - $ret[38] = 1;*/ + /** + * Skip this test on PHP 5.2. + * + * @since 0.9.0 + * + * @return bool Whether to skip this test. + */ + protected function shouldSkipTest() { + return version_compare( PHP_VERSION, '5.3.0', '<' ); + } - return $ret; + /** + * Returns the lines where errors should occur. + * + * @return array => + */ + public function getErrorList() { + $ret = array( + 4 => 2, + 17 => 2, + 29 => 5, + 37 => 1, + 41 => 1, + 42 => 1, + 49 => 5, + 58 => 3, + 67 => 1, + 68 => 1, + 69 => 1, + 71 => 1, + 72 => 1, + 81 => 3, + 82 => 1, + 85 => 1, + 91 => 2, + 92 => 1, + 94 => 1, + 95 => 1, + 97 => 1, + 98 => 1, + ); - }//end getErrorList() + /* + Uncomment when "$blank_line_check" parameter will be "true" by default. + $ret[29] += 1; + $ret[33] = 1; + $ret[36] = 1; + $ret[38] = 1; + */ - /** - * Returns the lines where warnings should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) - */ - public function getWarningList() - { - return array(); + return $ret; - }//end getWarningList() + } // end getErrorList() + /** + * Returns the lines where warnings should occur. + * + * @return array => + */ + public function getWarningList() { + return array(); -}//end class + } -?> +} // End class. diff --git a/WordPress/Tests/WhiteSpace/OperatorSpacingUnitTest.inc b/WordPress/Tests/WhiteSpace/OperatorSpacingUnitTest.inc index 82162e874c..bee440f694 100644 --- a/WordPress/Tests/WhiteSpace/OperatorSpacingUnitTest.inc +++ b/WordPress/Tests/WhiteSpace/OperatorSpacingUnitTest.inc @@ -1,20 +1,20 @@ - * @author Greg Sherwood - * @author Marc McIntyre - * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence - * @link http://pear.php.net/package/PHP_CodeSniffer + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ /** * Unit test class for the OperatorSpacing sniff. * - * A sniff unit test checks a .inc file for expected violations of a single - * coding standard. Expected errors and warnings are stored in this class. - * - * @category PHP - * @package PHP_CodeSniffer - * @author Akeda Bagus - * @author Greg Sherwood - * @author Marc McIntyre - * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence - * @version Release: @package_version@ - * @link http://pear.php.net/package/PHP_CodeSniffer + * @package WPCS\WordPressCodingStandards + * @since 2013-06-11 */ -class WordPress_Tests_WhiteSpace_OperatorSpacingUnitTest extends AbstractSniffUnitTest -{ - - - /** - * Returns the lines where errors should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of errors that should occur on that line. - * - * @return array(int => int) - */ - public function getErrorList() - { - return array( - 5 => 4, - 18 => 1, - 45 => 1, - 49 => 1, - ); - - }//end getErrorList() - - - /** - * Returns the lines where warnings should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) - */ - public function getWarningList() - { - return array(); - - }//end getWarningList() - - -}//end class - -?> +class WordPress_Tests_WhiteSpace_OperatorSpacingUnitTest extends AbstractSniffUnitTest { + + /** + * Returns the lines where errors should occur. + * + * @return array => + */ + public function getErrorList() { + return array( + 5 => 4, + 18 => 1, + 45 => 1, + 49 => 1, + ); + + } + + /** + * Returns the lines where warnings should occur. + * + * @return array => + */ + public function getWarningList() { + return array(); + + } + +} // End class. diff --git a/WordPress/Tests/XSS/EscapeOutputUnitTest.inc b/WordPress/Tests/XSS/EscapeOutputUnitTest.inc index 3132c19ee7..c009fe2349 100644 --- a/WordPress/Tests/XSS/EscapeOutputUnitTest.inc +++ b/WordPress/Tests/XSS/EscapeOutputUnitTest.inc @@ -1,25 +1,25 @@ -

-

-

+

+

+

'; -echo ent2ncr( $text ); // Bad +echo ent2ncr( $text ); // Bad. echo number_format( 1024 ); echo ent2ncr( esc_html( $_data ) ); -echo $foo ? $foo : 'no foo'; // Bad -echo empty( $foo ) ? 'no foo' : $foo; // Bad -echo $foo ? esc_html( $foo ) : 'no foo'; // OK +echo $foo ? $foo : 'no foo'; // Bad. +echo empty( $foo ) ? 'no foo' : $foo; // Bad. +echo $foo ? esc_html( $foo ) : 'no foo'; // Ok. -echo 4; // OK +echo 4; // Ok. -exit( $foo ); // Bad -exit( esc_html( $foo ) ); // OK +exit( $foo ); // Bad. +exit( esc_html( $foo ) ); // Ok. -die( $foo ); // Bad -die( esc_html( $foo ) ); // OK +die( $foo ); // Bad. +die( esc_html( $foo ) ); // Ok. -printf( 'Hello %s', $foo ); // Bad -printf( 'Hello %s', esc_html( $foo ) ); // OK -printf( 'Hello %s! Hi %s!', esc_html( $foo ), $bar ); // Bad +printf( 'Hello %s', $foo ); // Bad. +printf( 'Hello %s', esc_html( $foo ) ); // Ok. +printf( 'Hello %s! Hi %s!', esc_html( $foo ), $bar ); // Bad. -vprintf( 'Hello %s', array( $foo ) ); // Bad -vprintf( 'Hello %s', array( esc_html( $foo ) ) ); // OK +vprintf( 'Hello %s', array( $foo ) ); // Bad. +vprintf( 'Hello %s', array( esc_html( $foo ) ) ); // Ok. // The below checks that functions which are marked as needed further sanitization // don't spill over into later arguments when nested in a function call. There was @@ -81,12 +81,12 @@ vprintf( 'Hello %s', array( esc_html( $foo ) ) ); // OK // is marked as needing sanitization. do_something( _x( 'Some string', 'context', 'domain' ) - , array( $foo ) // OK + , array( $foo ) // Ok. ); // There was a bug where an empty exit followed by other code would give an error. if ( ! defined( 'ABSPATH' ) ) { - exit; // OK + exit; // Ok. } else { other(); } @@ -98,82 +98,85 @@ printf( // There were other long arguments down here "in real life", which is why this was multi-line. ); -wp_die( $message ); // Bad -wp_die( esc_html( $message ) ); // OK -wp_die( esc_html( $message ), $title ); // Bad -wp_die( esc_html( $message ), esc_html( $title ) ); // OK -wp_die( esc_html( $message ), '', array( 'back_link' => true ) ); // OK -wp_die( esc_html( $message ), '', array( 'back_link' => false ) ); // OK -wp_die( esc_html( $message ), '', array( 'response' => 200 ) ); // OK +wp_die( $message ); // Bad. +wp_die( esc_html( $message ) ); // Ok. +wp_die( esc_html( $message ), $title ); // Bad. +wp_die( esc_html( $message ), esc_html( $title ) ); // Ok. +wp_die( esc_html( $message ), '', array( 'back_link' => true ) ); // Ok. +wp_die( esc_html( $message ), '', array( 'back_link' => false ) ); // Ok. +wp_die( esc_html( $message ), '', array( 'response' => 200 ) ); // Ok. -echo '

', esc_html( $foo ), '

'; // OK -echo 'a', 'b'; // OK -echo 'Hello, ', $foo; // Bad -echo esc_html( $foo ), $bar; // Bad -echo (int) $foo, $bar; // Bad -echo (int) get_post_meta( $post_id, SOME_NUMBER, true ), do_something( $else ); // Bad +echo '

', esc_html( $foo ), '

'; // Ok. +echo 'a', 'b'; // Ok. +echo 'Hello, ', $foo; // Bad. +echo esc_html( $foo ), $bar; // Bad. +echo (int) $foo, $bar; // Bad. +echo (int) get_post_meta( $post_id, SOME_NUMBER, true ), do_something( $else ); // Bad. -wp_die( -1 ); // OK +wp_die( -1 ); // Ok. ?> -

- - +

+ + ' . sprintf( esc_html__( 'Some text -> %sLink text%s', 'textdomain' ), '', '' ). '

'; // OK +echo '

' . sprintf( esc_html__( 'Some text -> %sLink text%s', 'textdomain' ), '', '' ). '

'; // Ok. -echo '
' . sprintf( esc_html__( 'Found %d results', 'textdomain' ), (int) $result_count ) . '

'; // OK +echo '
' . sprintf( esc_html__( 'Found %d results', 'textdomain' ), (int) $result_count ) . '

'; // Ok. -echo sprintf( 'Hello %s', $foo ); // Bad -echo sprintf( 'Hello %s', esc_html( $foo ) ); // OK -echo sprintf( 'Hello %s! Hi %s!', esc_html( $foo ), $bar ); // Bad +echo sprintf( 'Hello %s', $foo ); // Bad. +echo sprintf( 'Hello %s', esc_html( $foo ) ); // Ok. +echo sprintf( 'Hello %s! Hi %s!', esc_html( $foo ), $bar ); // Bad. -echo vsprintf( 'Hello %s', array( $foo ) ); // Bad -echo vsprintf( 'Hello %s', array( esc_html( $foo ) ) ); // OK +echo vsprintf( 'Hello %s', array( $foo ) ); // Bad. +echo vsprintf( 'Hello %s', array( esc_html( $foo ) ) ); // Ok. -echo sprintf( __( 'Welcome to Genesis %s', 'genesis' ), PARENT_THEME_BRANCH ); // Bad x 2 -echo sprintf( esc_html__( 'Welcome to Genesis %s', 'genesis' ), esc_html( PARENT_THEME_BRANCH ) ); // OK +echo sprintf( __( 'Welcome to Genesis %s', 'genesis' ), PARENT_THEME_BRANCH ); // Bad x 2. +echo sprintf( esc_html__( 'Welcome to Genesis %s', 'genesis' ), esc_html( PARENT_THEME_BRANCH ) ); // Ok. -echo esc_html( strval( $_var ) ? $_var : gettype( $_var ) ); // OK -echo ( $is_hidden ) ? ' style="display:none;"' : ''; // OK -echo sprintf( 'Howdy, %s', esc_html( $name ? $name : __( 'Partner' ) ) ); // OK +echo esc_html( strval( $_var ) ? $_var : gettype( $_var ) ); // Ok. +echo ( $is_hidden ) ? ' style="display:none;"' : ''; // Ok. +echo sprintf( 'Howdy, %s', esc_html( $name ? $name : __( 'Partner' ) ) ); // Ok. -_e( 'Something' ); // Bad -esc_html_e( 'Something' ); // OK +_e( 'Something' ); // Bad. +esc_html_e( 'Something' ); // Ok. -echo $something // Bad - . esc_attr( 'baz-' // Rest is OK +echo $something // Bad. + . esc_attr( 'baz-' // Rest is OK. . $r . ( $r === $active_round ? ' foo' : '' ) . ( $r < $active_round ? ' bar' : '' ) ) . 'something'; -echo implode( '
', $items ); // Bad -echo implode( '
', urlencode_deep( $items ) ); // OK -echo implode( '
', array_map( 'esc_html', $items ) ); // OK -echo implode( '
', array_map( 'foo', $items ) ); // Bad -echo join( '
', $items ); // Bad -echo join( '
', array_map( 'esc_html', $items ) ); // OK +echo implode( '
', $items ); // Bad. +echo implode( '
', urlencode_deep( $items ) ); // Ok. +echo implode( '
', array_map( 'esc_html', $items ) ); // Ok. +echo implode( '
', array_map( 'foo', $items ) ); // Bad. +echo join( '
', $items ); // Bad. +echo join( '
', array_map( 'esc_html', $items ) ); // Ok. echo ''; + +_deprecated_hook( 'some_filter', '1.3.0', esc_html__( 'The $arg is deprecated.' ), 'some_other_filter' ); // Ok. +_deprecated_hook( "filter_{$context}", '1.3.0', __( 'The $arg is deprecated.' ), sprintf( __( 'Some parsed message %s', $variable ) ) ); // Bad. diff --git a/WordPress/Tests/XSS/EscapeOutputUnitTest.php b/WordPress/Tests/XSS/EscapeOutputUnitTest.php index f585f4592b..31ddd3e57a 100644 --- a/WordPress/Tests/XSS/EscapeOutputUnitTest.php +++ b/WordPress/Tests/XSS/EscapeOutputUnitTest.php @@ -1,48 +1,27 @@ - * @author Greg Sherwood - * @author Marc McIntyre - * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence - * @link http://pear.php.net/package/PHP_CodeSniffer + * @package WPCS\WordPressCodingStandards + * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards + * @license https://opensource.org/licenses/MIT MIT */ /** * Unit test class for the EscapeOutput sniff. * - * A sniff unit test checks a .inc file for expected violations of a single - * coding standard. Expected errors and warnings are stored in this class. - * - * @category PHP - * @package PHP_CodeSniffer - * @author Akeda Bagus - * @author Greg Sherwood - * @author Marc McIntyre - * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence - * @version Release: @package_version@ - * @link http://pear.php.net/package/PHP_CodeSniffer + * @package WPCS\WordPressCodingStandards + * @since 2013-06-11 */ -class WordPress_Tests_XSS_EscapeOutputUnitTest extends AbstractSniffUnitTest -{ - +class WordPress_Tests_XSS_EscapeOutputUnitTest extends AbstractSniffUnitTest { - /** - * Returns the lines where errors should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of errors that should occur on that line. - * - * @return array(int => int) - */ - public function getErrorList() - { - return array( + /** + * Returns the lines where errors should occur. + * + * @return array => + */ + public function getErrorList() { + return array( 17 => 1, 19 => 1, 36 => 1, @@ -78,26 +57,19 @@ public function getErrorList() 169 => 1, 172 => 1, 173 => 1, + 182 => 3, ); - }//end getErrorList() - - - /** - * Returns the lines where warnings should occur. - * - * The key of the array should represent the line number and the value - * should represent the number of warnings that should occur on that line. - * - * @return array(int => int) - */ - public function getWarningList() - { - return array(); - - }//end getWarningList() + } // end getErrorList() + /** + * Returns the lines where warnings should occur. + * + * @return array => + */ + public function getWarningList() { + return array(); -}//end class + } -?> +} // End class. diff --git a/bin/phpcs.xml b/bin/phpcs.xml new file mode 100644 index 0000000000..f6a7e6e234 --- /dev/null +++ b/bin/phpcs.xml @@ -0,0 +1,12 @@ + + + The Coding standard for the WordPress Coding Standards itself. + + + + + + + + + diff --git a/composer.json b/composer.json index 22dc43551f..7c047bb9f5 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,7 @@ } ], "require" : { - "squizlabs/php_codesniffer": "~2.2" + "squizlabs/php_codesniffer": "^2.6" }, "minimum-stability" : "RC", "support" : { diff --git a/myconfig.ini b/myconfig.ini new file mode 100644 index 0000000000..8c5f68f520 --- /dev/null +++ b/myconfig.ini @@ -0,0 +1,3 @@ +; Allow ASP-style <% %> tags. +; http://php.net/asp-tags +asp_tags = On