Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DisallowShortOpenTag: throw warning for potential short open tags in inline HTML #1400

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,17 @@ class Generic_Sniffs_PHP_DisallowShortOpenTagSniff implements PHP_CodeSniffer_Sn
*/
public function register()
{
return array(
T_OPEN_TAG,
T_OPEN_TAG_WITH_ECHO,
);
$targets = array(
T_OPEN_TAG,
T_OPEN_TAG_WITH_ECHO,
);

$shortOpenTags = (boolean) ini_get('short_open_tag');
if ($shortOpenTags === false) {
$targets[] = T_INLINE_HTML;
}

return $targets;

}//end register()

Expand All @@ -57,12 +64,12 @@ public function register()
*/
public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();
$openTag = $tokens[$stackPtr];
$tokens = $phpcsFile->getTokens();
$token = $tokens[$stackPtr];

if ($openTag['content'] === '<?') {
if ($token['code'] === T_OPEN_TAG && $token['content'] === '<?') {
$error = 'Short PHP opening tag used; expected "<?php" but found "%s"';
$data = array($openTag['content']);
$data = array($token['content']);
$fix = $phpcsFile->addFixableError($error, $stackPtr, 'Found', $data);
if ($fix === true) {
$phpcsFile->fixer->replaceToken($stackPtr, '<?php');
Expand All @@ -73,12 +80,12 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
$phpcsFile->recordMetric($stackPtr, 'PHP short open tag used', 'no');
}

if ($openTag['code'] === T_OPEN_TAG_WITH_ECHO) {
if ($token['code'] === T_OPEN_TAG_WITH_ECHO) {
$nextVar = $tokens[$phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr + 1), null, true)];
$error = 'Short PHP opening tag used with echo; expected "<?php echo %s ..." but found "%s %s ..."';
$data = array(
$nextVar['content'],
$openTag['content'],
$token['content'],
$nextVar['content'],
);
$fix = $phpcsFile->addFixableError($error, $stackPtr, 'EchoFound', $data);
Expand All @@ -91,7 +98,79 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
}
}

if ($token['code'] === T_INLINE_HTML) {
$content = $token['content'];
$openerFound = strpos($content, '<?');

if ($openerFound === false) {
return;
}

$closerFound = false;

// Inspect current token and subsequent inline HTML token to find a close tag.
for ($i = $stackPtr; $i < $phpcsFile->numTokens; $i++) {
if ($tokens[$i]['code'] !== T_INLINE_HTML) {
break;
}

$closerFound = strrpos($tokens[$i]['content'], '?>');
if ($closerFound !== false) {
if ($i !== $stackPtr) {
break;
} else if ($closerFound > $openerFound) {
break;
} else {
$closerFound = false;
}
}
}

if ($closerFound !== false) {
$error = 'Possible use of short open tags detected. Needs manual inspection. Found: %s';
$snippet = $this->getSnippet($content, '<?');
$data = array('<?'.$snippet);

$phpcsFile->addWarning($error, $stackPtr, 'PossibleShortOpenTagFound', $data);

// Skip forward to the token containing the closer.
if (($i - 1) > $stackPtr) {
return $i;
}
}
}//end if

}//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
*/
protected function getSnippet($content, $start_at = '', $length = 40)
{
$start_pos = 0;

if ($start_at !== '') {
$start_pos = strpos($content, $start_at);
if ($start_pos !== false) {
$start_pos += strlen($start_at);
}
}

$snippet = substr($content, $start_pos, $length);
if ((strlen($content) - $start_pos) > $length) {
$snippet .= '...';
}

return $snippet;

}//end getSnippet()


}//end class
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Test warning for when short_open_tag is off.

Some content <? echo $var; ?> Some more content

// Test multi-line.
Some content <?
echo $var;
?> Some more content

// Make sure skipping works.
Some content <?
echo '<?';
?> Some more content

// Only recognize closing tag after opener.
Some?> content <?
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Test warning for PHP < 5.4.
Some content <?=
$var;
?> Some more content
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ protected function getTestFiles($testFileBase)
$option = (boolean) ini_get('short_open_tag');
if ($option === true || defined('HHVM_VERSION') === true) {
$testFiles[] = $testFileBase.'2.inc';
} else {
$testFiles[] = $testFileBase.'3.inc';

if (PHP_VERSION_ID < 50400) {
$testFiles[] = $testFileBase.'4.inc';
}
}

return $testFiles;
Expand Down Expand Up @@ -94,9 +100,22 @@ public function getErrorList($testFile='')
*
* @return array<int, int>
*/
public function getWarningList()
public function getWarningList($testFile='')
{
return array();
switch ($testFile) {
case 'DisallowShortOpenTagUnitTest.3.inc':
return array(
13 => 1,
16 => 1,
21 => 1,
);
case 'DisallowShortOpenTagUnitTest.4.inc':
return array(
2 => 1,
);
default:
return array();
}//end switch

}//end getWarningList()

Expand Down
2 changes: 2 additions & 0 deletions package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,8 @@ http://pear.php.net/dtd/package-2.0.xsd">
<file baseinstalldir="PHP" name="DisallowShortOpenTagUnitTest.1.inc.fixed" role="test" />
<file baseinstalldir="PHP" name="DisallowShortOpenTagUnitTest.2.inc" role="test" />
<file baseinstalldir="PHP" name="DisallowShortOpenTagUnitTest.2.inc.fixed" role="test" />
<file baseinstalldir="PHP" name="DisallowShortOpenTagUnitTest.3.inc" role="test" />
<file baseinstalldir="PHP" name="DisallowShortOpenTagUnitTest.4.inc" role="test" />
<file baseinstalldir="PHP" name="DisallowShortOpenTagUnitTest.php" role="test">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
Expand Down