123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- <?php
- /**
- * PHPCompatibility, an external standard for PHP_CodeSniffer.
- *
- * @package PHPCompatibility
- * @copyright 2012-2019 PHPCompatibility Contributors
- * @license https://opensource.org/licenses/LGPL-3.0 LGPL3
- * @link https://github.com/PHPCompatibility/PHPCompatibility
- */
- namespace PHPCompatibility\Sniffs\FunctionUse;
- use PHPCompatibility\Sniff;
- use PHP_CodeSniffer_File as File;
- use PHP_CodeSniffer_Tokens as Tokens;
- /**
- * Detect usage of `func_get_args()`, `func_get_arg()` and `func_num_args()` in invalid context.
- *
- * Checks for:
- * - Prior to PHP 5.3, these functions could not be used as a function call parameter.
- * - Calling these functions from the outermost scope of a file which has been included by
- * calling `include` or `require` from within a function in the calling file, worked
- * prior to PHP 5.3. As of PHP 5.3, this will generate a warning and will always return false/-1.
- * If the file was called directly or included in the global scope, calls to these
- * functions would already generate a warning prior to PHP 5.3.
- *
- * PHP version 5.3
- *
- * @link https://www.php.net/manual/en/migration53.incompatible.php
- *
- * @since 8.2.0
- */
- class ArgumentFunctionsUsageSniff extends Sniff
- {
- /**
- * The target functions for this sniff.
- *
- * @since 8.2.0
- *
- * @var array
- */
- protected $targetFunctions = array(
- 'func_get_args' => true,
- 'func_get_arg' => true,
- 'func_num_args' => true,
- );
- /**
- * Returns an array of tokens this test wants to listen for.
- *
- * @since 8.2.0
- *
- * @return array
- */
- public function register()
- {
- return array(\T_STRING);
- }
- /**
- * Processes this test, when one of its tokens is encountered.
- *
- * @since 8.2.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(File $phpcsFile, $stackPtr)
- {
- $tokens = $phpcsFile->getTokens();
- $functionLc = strtolower($tokens[$stackPtr]['content']);
- if (isset($this->targetFunctions[$functionLc]) === false) {
- return;
- }
- // Next non-empty token should be the open parenthesis.
- $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true, null, true);
- if ($nextNonEmpty === false || $tokens[$nextNonEmpty]['code'] !== \T_OPEN_PARENTHESIS) {
- return;
- }
- $ignore = array(
- \T_DOUBLE_COLON => true,
- \T_OBJECT_OPERATOR => true,
- \T_FUNCTION => true,
- \T_NEW => true,
- );
- $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true);
- if (isset($ignore[$tokens[$prevNonEmpty]['code']]) === true) {
- // Not a call to a PHP function.
- return;
- } elseif ($tokens[$prevNonEmpty]['code'] === \T_NS_SEPARATOR && $tokens[$prevNonEmpty - 1]['code'] === \T_STRING) {
- // Namespaced function.
- return;
- }
- $data = $tokens[$stackPtr]['content'];
- /*
- * Check for use of the functions in the global scope.
- *
- * As PHPCS can not determine whether a file is included from within a function in
- * another file, so always throw a warning/error.
- */
- if ($phpcsFile->hasCondition($stackPtr, array(\T_FUNCTION, \T_CLOSURE)) === false) {
- $isError = false;
- $message = 'Use of %s() outside of a user-defined function is only supported if the file is included from within a user-defined function in another file prior to PHP 5.3.';
- if ($this->supportsAbove('5.3') === true) {
- $isError = true;
- $message .= ' As of PHP 5.3, it is no longer supported at all.';
- }
- $this->addMessage($phpcsFile, $message, $stackPtr, $isError, 'OutsideFunctionScope', $data);
- }
- /*
- * Check for use of the functions as a parameter in a function call.
- */
- if ($this->supportsBelow('5.2') === false) {
- return;
- }
- if (isset($tokens[$stackPtr]['nested_parenthesis']) === false) {
- return;
- }
- $throwError = false;
- $closer = end($tokens[$stackPtr]['nested_parenthesis']);
- if (isset($tokens[$closer]['parenthesis_owner'])
- && $tokens[$tokens[$closer]['parenthesis_owner']]['type'] === 'T_CLOSURE'
- ) {
- $throwError = true;
- } else {
- $opener = key($tokens[$stackPtr]['nested_parenthesis']);
- $prevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($opener - 1), null, true);
- if ($tokens[$prevNonEmpty]['code'] !== \T_STRING) {
- return;
- }
- $prevPrevNonEmpty = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prevNonEmpty - 1), null, true);
- if ($tokens[$prevPrevNonEmpty]['code'] === \T_FUNCTION) {
- return;
- }
- $throwError = true;
- }
- if ($throwError === false) {
- return;
- }
- $phpcsFile->addError(
- '%s() could not be used in parameter lists prior to PHP 5.3.',
- $stackPtr,
- 'InParameterList',
- $data
- );
- }
- }
|