Skip to content

Commit

Permalink
✨ PHP 4.2/7.0: New sniff to detect passing string literal category to…
Browse files Browse the repository at this point in the history
… setlocale()

> "Support for the category parameter passed as a string has been removed.
> Only LC_* constants can be used as of this version [7.0.0]. "

Refs:
* http://php.net/manual/en/migration70.changed-functions.php#migration70.changed-functions.core
* http://php.net/manual/en/function.setlocale.php
* https://web.archive.org/web/20061114024645/http://www.php.net:80/manual/en/function.setlocale.php
  • Loading branch information
jrfnl committed Jun 10, 2018
1 parent 2362a4e commit 5c3b217
Show file tree
Hide file tree
Showing 3 changed files with 197 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<?php
/**
* \PHPCompatibility\Sniffs\FunctionParameters\SetlocaleStringSniff.
*
* PHP version 4.2
* PHP version 7.0
*
* @category PHP
* @package PHPCompatibility\FunctionParameters
* @author Juliette Reinders Folmer <phpcompatibility_nospam@adviesenzo.nl>
*/

namespace PHPCompatibility\Sniffs\FunctionParameters;

use PHPCompatibility\AbstractFunctionCallParameterSniff;

/**
* \PHPCompatibility\Sniffs\FunctionParameters\SetlocaleStringSniff.
*
* Detect: Support for the category parameter passed as a string has been removed.
* Only LC_* constants can be used as of this version [7.0.0].
*
* PHP version 4.2
* PHP version 7.0
*
* @category PHP
* @package PHPCompatibility\FunctionParameters
* @author Juliette Reinders Folmer <phpcompatibility_nospam@adviesenzo.nl>
*/
class SetlocaleStringSniff extends AbstractFunctionCallParameterSniff
{

/**
* Functions to check for.
*
* @var array
*/
protected $targetFunctions = array(
'setlocale' => true,
);


/**
* Do a version check to determine if this sniff needs to run at all.
*
* @return bool
*/
protected function bowOutEarly()
{
return ($this->supportsAbove('4.2') === false);
}


/**
* Process the parameters of a matched function.
*
* @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
* @param int $stackPtr The position of the current token in the stack.
* @param string $functionName The token content (function name) which was matched.
* @param array $parameters Array with information about the parameters.
*
* @return int|void Integer stack pointer to skip forward or void to continue
* normal file processing.
*/
public function processParameters(\PHP_CodeSniffer_File $phpcsFile, $stackPtr, $functionName, $parameters)
{
if (isset($parameters[1]) === false) {
return;
}

$tokens = $phpcsFile->getTokens();
$targetParam = $parameters[1];

for ($i = $targetParam['start']; $i <= $targetParam['end']; $i++) {
if ($tokens[$i]['code'] !== T_CONSTANT_ENCAPSED_STRING
&& $tokens[$i]['code'] !== T_DOUBLE_QUOTED_STRING
) {
continue;
}

$message = 'Passing the $category as a string to setlocale() has been deprecated since PHP 4.2';
$isError = false;
$errorCode = 'Deprecated';
$data = array($targetParam['raw']);

if ($this->supportsAbove('7.0') === true) {
$message .= ' and is removed since PHP 7.0';
$isError = true;
$errorCode = 'Removed';
}

$message .= '; Pass one of the LC_* constants instead. Found: %s';

$this->addMessage($phpcsFile, $message, $i, $isError, $errorCode, $data);
break;
}
}
}//end class
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php
/**
* Passing literal string $category to setlocale() sniff test file.
*
* @package PHPCompatibility
*/

namespace PHPCompatibility\Tests\Sniffs\FunctionParameters;

use PHPCompatibility\Tests\BaseSniffTest;

/**
* Passing literal string $category to setlocale() sniff tests.
*
* @group setlocaleString
* @group functionParameterValues
*
* @covers \PHPCompatibility\Sniffs\FunctionParameters\SetlocaleStringSniff
*
* @uses \PHPCompatibility\Tests\BaseSniffTest
* @package PHPCompatibility\FunctionParameters
* @author Juliette Reinders Folmer <phpcompatibility_nospam@adviesenzo.nl>
*/
class SetlocaleStringSniffTest extends BaseSniffTest
{

const TEST_FILE = 'Sniffs/FunctionParameters/SetlocaleStringTestCases.inc';

/**
* testSetlocaleString
*
* @dataProvider dataSetlocaleString
*
* @param int $line Line number where the error should occur.
*
* @return void
*/
public function testSetlocaleString($line)
{
$file = $this->sniffFile(self::TEST_FILE, '4.2');
$this->assertWarning($file, $line, 'Passing the $category as a string to setlocale() has been deprecated since PHP 4.2; Pass one of the LC_* constants instead.');

$file = $this->sniffFile(self::TEST_FILE, '7.0');
$this->assertError($file, $line, 'Passing the $category as a string to setlocale() has been deprecated since PHP 4.2 and is removed since PHP 7.0; Pass one of the LC_* constants instead.');
}

/**
* dataSetlocaleString
*
* @see testSetlocaleString()
*
* @return array
*/
public function dataSetlocaleString()
{
return array(
array(9),
array(10),
);
}


/**
* testNoFalsePositives
*
* @return void
*/
public function testNoFalsePositives()
{
$file = $this->sniffFile(self::TEST_FILE, '7.0');

// No errors expected on the first 7 lines.
for ($line = 1; $line <= 7; $line++) {
$this->assertNoViolation($file, $line);
}
}


/**
* Verify no notices are thrown at all.
*
* @return void
*/
public function testNoViolationsInFileOnValidVersion()
{
$file = $this->sniffFile(self::TEST_FILE, '4.1');
$this->assertNoViolation($file);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

// OK.
setlocale();
setlocale(LC_ALL, 'nl_NL');
setlocale($category, $lang); // Can't be determined.

// Not OK.
setlocale('LC_ALL', 'nl_NL');
setlocale('LC_'.$category, $lang);

0 comments on commit 5c3b217

Please sign in to comment.