-
-
Save voku/d7d530ce2c072f5b4bdaafb040d1eb55 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
use PHP_CodeSniffer\Files\File; | |
use PHP_CodeSniffer\Sniffs\Sniff; | |
use PHP_Codesniffer\Util\Tokens; | |
final class VdmgForbiddenGlobalSniff implements Sniff { | |
/** | |
* @var string[] | |
* | |
* TODO@lars: maybe we can enable more restrictions for global variables in the future | |
*/ | |
private $globalVariables = [ | |
'$argv', | |
'$Brand', // TODO@lars -> remove | |
'$catalog_status_array', | |
'$contact_anrede_select_array', | |
'$contact_country_select_array', | |
'$contact_lieferant_type_select_array', | |
'$controlling_diff_mode_select_array', | |
]; | |
/** | |
* @param File $file | |
* @param int $stackPtr | |
* | |
* @return void | |
*/ | |
public function process(File $file, $stackPtr): void { | |
$fileNameAndPath = $file->getFilename(); | |
/* | |
if ( | |
strpos($fileNameAndPath, 'application_top.php') !== false | |
|| | |
strpos($fileNameAndPath, 'defines.php') !== false | |
) { | |
return; | |
} | |
*/ | |
$tokensAll = $file->getTokens(); | |
$currentToken = $tokensAll[$stackPtr]; | |
if (!is_array($currentToken)) { | |
return; | |
} | |
if ($currentToken['content'] === '$GLOBALS') { | |
$bracketPtr = $file->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); | |
// Check if this is an array. | |
if ( | |
$bracketPtr === false | |
|| | |
$tokensAll[$bracketPtr]['code'] !== \T_OPEN_SQUARE_BRACKET | |
|| | |
!isset($tokensAll[$bracketPtr]['bracket_closer']) | |
) { | |
return; | |
} | |
// Retrieve the array key and avoid getting tripped up by some simple obfuscation. | |
$var_name = ''; | |
$start = $bracketPtr + 1; | |
for ($ptr = $start; $ptr < $tokensAll[$bracketPtr]['bracket_closer']; $ptr++) { | |
/* | |
* If the globals array key contains a variable, constant, function call | |
* or interpolated variable, bow out. | |
*/ | |
if ( | |
$tokensAll[$ptr]['code'] === \T_VARIABLE | |
|| | |
$tokensAll[$ptr]['code'] === \T_STRING | |
|| | |
$tokensAll[$ptr]['code'] === \T_DOUBLE_QUOTED_STRING | |
) { | |
return; | |
} | |
if ($tokensAll[$ptr]['code'] === \T_CONSTANT_ENCAPSED_STRING) { | |
$var_name .= preg_replace('`^([\'"])(.*)\1$`Ds', '$2', $tokensAll[$ptr]['content']); | |
} | |
} | |
if ($var_name === '') { | |
// Shouldn't happen, but just in case. | |
return; | |
} | |
if (in_array('$' . $var_name, $this->globalVariables, true)) { | |
return; | |
} | |
$file->addWarning( | |
sprintf('GLOBALS["%s"] should not be used: use ServiceContainer::* or YOURConst::* classes', $var_name), | |
$stackPtr, | |
$currentToken['content'] | |
); | |
} else { | |
// Are we a global declaration? | |
// Search backwards for first token that isn't whitespace/comment, comma or variable. | |
$ignore = Tokens::$emptyTokens; | |
$ignore[\T_VARIABLE] = \T_VARIABLE; | |
$ignore[T_COMMA] = T_COMMA; | |
$globalPtr = $file->findPrevious($ignore, $stackPtr - 1, null, true, null, true); | |
if ( | |
$globalPtr === false | |
|| | |
$tokensAll[$globalPtr]['code'] !== \T_GLOBAL | |
) { | |
return; | |
} | |
if (in_array($currentToken['content'], $this->globalVariables, true)) { | |
return; | |
} | |
$file->addWarning( | |
sprintf('global "%s" should not be used: use ServiceContainer::* or YOURConst::* classes', $currentToken['content']), | |
$stackPtr, | |
$currentToken['content'] | |
); | |
} | |
} | |
/** | |
* @return int[] | |
*/ | |
public function register() { | |
return [ | |
\T_VARIABLE, | |
]; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment