Skip to content

Commit f4da06d

Browse files
committed
MAGETWO-84354: Copy EQP sniffs to Magento 2 Core repo
1 parent 5aaaeff commit f4da06d

File tree

5 files changed

+388
-0
lines changed

5 files changed

+388
-0
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Sniffs\LanguageConstructs;
7+
8+
use PHP_CodeSniffer\Sniffs\Sniff;
9+
use PHP_CodeSniffer\Files\File;
10+
11+
/**
12+
* Detects GOTO usage.
13+
*/
14+
class GotoSniff implements Sniff
15+
{
16+
/**
17+
* String representation of warning.
18+
*
19+
* @var string
20+
*/
21+
protected $errorMessage = 'Use of goto is discouraged.';
22+
23+
/**
24+
* Warning violation code.
25+
*
26+
* @var string
27+
*/
28+
protected $errorCode = 'FoundGoto';
29+
30+
/**
31+
* {@inheritdoc}
32+
*/
33+
public function register()
34+
{
35+
return [T_GOTO];
36+
}
37+
38+
/**
39+
* {@inheritdoc}
40+
*/
41+
public function process(File $phpcsFile, $stackPtr)
42+
{
43+
$phpcsFile->addError($this->errorMessage, $stackPtr, $this->errorCode);
44+
}
45+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Sniffs\LanguageConstructs;
7+
8+
use PHP_CodeSniffer\Sniffs\Sniff;
9+
use PHP_CodeSniffer\Files\File;
10+
11+
/**
12+
* Detects possible usage of discouraged language constructs.
13+
*/
14+
class LanguageConstructsSniff implements Sniff
15+
{
16+
/**
17+
* String representation of error.
18+
*
19+
* @var string
20+
*/
21+
protected $errorMessage = 'Use of %s language construct is discouraged.';
22+
23+
/**
24+
* String representation of backtick error.
25+
*
26+
* @var string
27+
*/
28+
// @codingStandardsIgnoreLine
29+
protected $errorMessageBacktick = 'Incorrect usage of back quote string constant. Back quotes should be always inside strings.';
30+
31+
/**
32+
* Backtick violation code.
33+
*
34+
* @var string
35+
*/
36+
protected $backtickCode = 'WrongBackQuotesUsage';
37+
38+
/**
39+
* Exit usage code.
40+
*
41+
* @var string
42+
*/
43+
protected $exitUsage = 'ExitUsage';
44+
45+
/**
46+
* Direct output code.
47+
*
48+
* @var string
49+
*/
50+
protected $directOutput = 'DirectOutput';
51+
52+
/**
53+
* {@inheritdoc}
54+
*/
55+
public function register()
56+
{
57+
return [
58+
T_EXIT,
59+
T_ECHO,
60+
T_PRINT,
61+
T_BACKTICK,
62+
];
63+
}
64+
65+
/**
66+
* {@inheritdoc}
67+
*/
68+
public function process(File $phpcsFile, $stackPtr)
69+
{
70+
$tokens = $phpcsFile->getTokens();
71+
if ($tokens[$stackPtr]['code'] === T_BACKTICK) {
72+
if ($phpcsFile->findNext(T_BACKTICK, $stackPtr + 1)) {
73+
return;
74+
}
75+
$phpcsFile->addError($this->errorMessageBacktick, $stackPtr, $this->backtickCode);
76+
return;
77+
}
78+
if ($tokens[$stackPtr]['code'] === T_EXIT) {
79+
$code = $this->exitUsage;
80+
} else {
81+
$code = $this->directOutput;
82+
}
83+
$phpcsFile->addError($this->errorMessage, $stackPtr, $code, [$tokens[$stackPtr]['content']]);
84+
}
85+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Sniffs\Security;
7+
8+
use PHP_CodeSniffer\Sniffs\Sniff;
9+
use PHP_CodeSniffer\Files\File;
10+
use PHP_CodeSniffer\Util\Tokens;
11+
12+
/**
13+
* Detects executable regular expressions.
14+
*/
15+
class ExecutableRegExSniff implements Sniff
16+
{
17+
/**
18+
* String representation of error.
19+
*
20+
* @var string
21+
*/
22+
// @codingStandardsIgnoreLine
23+
protected $errorMessage = "Possible executable regular expression in %s. Make sure that the pattern doesn't contain 'e' modifier";
24+
25+
/**
26+
* Error violation code.
27+
*
28+
* @var string
29+
*/
30+
protected $errorCode = 'PossibleExecutableRegEx';
31+
32+
/**
33+
* Observed function.
34+
*
35+
* @var array
36+
*/
37+
protected $function = 'preg_replace';
38+
39+
/**
40+
* List of ignored tokens.
41+
*
42+
* @var array
43+
*/
44+
protected $ignoreTokens = [
45+
T_DOUBLE_COLON,
46+
T_OBJECT_OPERATOR,
47+
T_FUNCTION,
48+
T_CONST,
49+
T_CLASS,
50+
];
51+
52+
/**
53+
* {@inheritdoc}
54+
*/
55+
public function register()
56+
{
57+
return [T_STRING];
58+
}
59+
60+
/**
61+
* {@inheritdoc}
62+
*/
63+
public function process(File $phpcsFile, $stackPtr)
64+
{
65+
$tokens = $phpcsFile->getTokens();
66+
if ($tokens[$stackPtr]['content'] !== $this->function) {
67+
return;
68+
}
69+
$prevToken = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true);
70+
if (in_array($tokens[$prevToken]['code'], $this->ignoreTokens)) {
71+
return;
72+
}
73+
$nextToken = $phpcsFile->findNext([T_WHITESPACE, T_OPEN_PARENTHESIS], $stackPtr + 1, null, true);
74+
if (in_array($tokens[$nextToken]['code'], Tokens::$stringTokens)
75+
&& preg_match('/[#\/|~\}\)][imsxADSUXJu]*e[imsxADSUXJu]*.$/', $tokens[$nextToken]['content'])
76+
) {
77+
$phpcsFile->addError(
78+
$this->errorMessage,
79+
$stackPtr,
80+
$this->errorCode,
81+
[$tokens[$stackPtr]['content']]
82+
);
83+
}
84+
}
85+
}
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Sniffs\Strings;
7+
8+
use PHP_CodeSniffer\Sniffs\Sniff;
9+
use PHP_CodeSniffer\Files\File;
10+
11+
/**
12+
* Detects misusing of IS_IDENTICAL operators.
13+
*/
14+
class StringPositionSniff implements Sniff
15+
{
16+
/**
17+
* String representation of error.
18+
*
19+
* @var string
20+
*/
21+
protected $errorMessage = 'Identical operator === is not used for testing the return value of %s function';
22+
23+
/**
24+
* Error violation code.
25+
*
26+
* @var string
27+
*/
28+
protected $errorCode = 'ImproperValueTesting';
29+
30+
/**
31+
* Searched functions.
32+
*
33+
* @var array
34+
*/
35+
protected $functions = [
36+
'strpos',
37+
'stripos',
38+
];
39+
40+
/**
41+
* All tokens from current file.
42+
*
43+
* @var array
44+
*/
45+
protected $tokens = [];
46+
47+
/**
48+
* PHP_CodeSniffer file.
49+
*
50+
* @var File
51+
*/
52+
protected $file;
53+
54+
/**
55+
* Left limit for search of identical operators.
56+
*
57+
* @var int
58+
*/
59+
protected $leftLimit;
60+
61+
/**
62+
* Right limit for search of identical operators.
63+
*
64+
* @var int
65+
*/
66+
protected $rightLimit;
67+
68+
/**
69+
* List of tokens which declares left bound of current scope.
70+
*
71+
* @var array
72+
*/
73+
protected $leftRangeTokens = [
74+
T_IS_IDENTICAL,
75+
T_IS_NOT_IDENTICAL,
76+
T_OPEN_PARENTHESIS,
77+
T_BOOLEAN_AND,
78+
T_BOOLEAN_OR,
79+
];
80+
81+
/**
82+
* List of tokens which declares right bound of current scope.
83+
*
84+
* @var array
85+
*/
86+
protected $rightRangeTokens = [
87+
T_IS_IDENTICAL,
88+
T_IS_NOT_IDENTICAL,
89+
T_CLOSE_PARENTHESIS,
90+
T_BOOLEAN_AND,
91+
T_BOOLEAN_OR,
92+
];
93+
94+
/**
95+
* List of tokens which declares identical operators.
96+
*
97+
* @var array
98+
*/
99+
protected $identical = [
100+
T_IS_IDENTICAL,
101+
T_IS_NOT_IDENTICAL,
102+
];
103+
104+
/**
105+
* {@inheritdoc}
106+
*/
107+
public function register()
108+
{
109+
return [T_IF, T_ELSEIF];
110+
}
111+
112+
/**
113+
* {@inheritdoc}
114+
*/
115+
public function process(File $phpcsFile, $stackPtr)
116+
{
117+
$this->tokens = $phpcsFile->getTokens();
118+
$this->file = $phpcsFile;
119+
$this->leftLimit = $open = $this->tokens[$stackPtr]['parenthesis_opener'];
120+
$this->rightLimit = $close = $this->tokens[$stackPtr]['parenthesis_closer'];
121+
for ($i = ($open + 1); $i < $close; $i++) {
122+
if (($this->tokens[$i]['code'] === T_STRING && in_array($this->tokens[$i]['content'], $this->functions))
123+
&& (!$this->findIdentical($i - 1, $this->findFunctionParenthesisCloser($i) + 1))
124+
) {
125+
$foundFunctionName = $this->tokens[$i]['content'];
126+
$phpcsFile->addError($this->errorMessage, $i, $this->errorCode, [$foundFunctionName]);
127+
}
128+
}
129+
}
130+
131+
/**
132+
* Recursively finds identical operators in current scope.
133+
*
134+
* @param int $leftCurrentPosition
135+
* @param int $rightCurrentPosition
136+
* @return bool
137+
*/
138+
protected function findIdentical($leftCurrentPosition, $rightCurrentPosition)
139+
{
140+
$leftBound = $this->file->findPrevious($this->leftRangeTokens, $leftCurrentPosition, $this->leftLimit - 1);
141+
$rightBound = $this->file->findNext($this->rightRangeTokens, $rightCurrentPosition, $this->rightLimit + 1);
142+
$leftToken = $this->tokens[$leftBound];
143+
$rightToken = $this->tokens[$rightBound];
144+
if ($leftToken['code'] === T_OPEN_PARENTHESIS && $rightToken['code'] === T_CLOSE_PARENTHESIS) {
145+
return $this->findIdentical($leftBound - 1, $rightBound + 1);
146+
} else {
147+
return (
148+
in_array($leftToken['code'], $this->identical) || in_array($rightToken['code'], $this->identical)
149+
) ?: false;
150+
}
151+
}
152+
153+
/**
154+
* Finds the position of close parenthesis of detected function.
155+
*
156+
* @param int $currentPosition
157+
* @return mixed
158+
*/
159+
protected function findFunctionParenthesisCloser($currentPosition)
160+
{
161+
$nextOpenParenthesis = $this->file->findNext(T_OPEN_PARENTHESIS, $currentPosition, $this->rightLimit);
162+
return $nextOpenParenthesis ? $this->tokens[$nextOpenParenthesis]['parenthesis_closer'] : false;
163+
}
164+
}

0 commit comments

Comments
 (0)