Initial Commit
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
/**
|
||||
* Ensures that all action classes throw ChannelExceptions only.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category PHP
|
||||
* @package PHP_CodeSniffer_MySource
|
||||
* @author Greg Sherwood <gsherwood@squiz.net>
|
||||
* @copyright 2006-2011 Squiz Pty Ltd (ABN 77 084 670 600)
|
||||
* @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
|
||||
* @link http://pear.php.net/package/PHP_CodeSniffer
|
||||
*/
|
||||
|
||||
/**
|
||||
* Ensures that all action classes throw ChannelExceptions only.
|
||||
*
|
||||
* @category PHP
|
||||
* @package PHP_CodeSniffer_MySource
|
||||
* @author Greg Sherwood <gsherwood@squiz.net>
|
||||
* @copyright 2006-2011 Squiz Pty Ltd (ABN 77 084 670 600)
|
||||
* @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
|
||||
* @version Release: 1.3.3
|
||||
* @link http://pear.php.net/package/PHP_CodeSniffer
|
||||
*/
|
||||
class MySource_Sniffs_Channels_ChannelExceptionSniff implements PHP_CodeSniffer_Sniff
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Returns an array of tokens this test wants to listen for.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
return array(T_THROW);
|
||||
|
||||
}//end register()
|
||||
|
||||
|
||||
/**
|
||||
* Processes this sniff, when one of its tokens is encountered.
|
||||
*
|
||||
* @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(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
|
||||
{
|
||||
$fileName = strtolower($phpcsFile->getFilename());
|
||||
$matches = array();
|
||||
if (preg_match('|/systems/(.*)/([^/]+)?actions.inc$|', $fileName, $matches) === 0) {
|
||||
// This is not an actions.inc file.
|
||||
return;
|
||||
}
|
||||
|
||||
$tokens = $phpcsFile->getTokens();
|
||||
|
||||
$exception = $phpcsFile->findNext(array(T_STRING, T_VARIABLE), ($stackPtr + 1));
|
||||
$exceptionName = $tokens[$exception]['content'];
|
||||
|
||||
if ($exceptionName !== 'ChannelException') {
|
||||
$data = array($exceptionName);
|
||||
$error = 'Channel actions can only throw ChannelException; found "%s"';
|
||||
$phpcsFile->addError($error, $exception, 'WrongExceptionType', $data);
|
||||
}
|
||||
|
||||
}//end process()
|
||||
|
||||
|
||||
}//end class
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
/**
|
||||
* Ensures that self is not used to call public method in action classes.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category PHP
|
||||
* @package PHP_CodeSniffer_MySource
|
||||
* @author Greg Sherwood <gsherwood@squiz.net>
|
||||
* @copyright 2006-2011 Squiz Pty Ltd (ABN 77 084 670 600)
|
||||
* @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
|
||||
* @link http://pear.php.net/package/PHP_CodeSniffer
|
||||
*/
|
||||
|
||||
/**
|
||||
* Ensures that self is not used to call public method in action classes.
|
||||
*
|
||||
* @category PHP
|
||||
* @package PHP_CodeSniffer_MySource
|
||||
* @author Greg Sherwood <gsherwood@squiz.net>
|
||||
* @copyright 2006-2011 Squiz Pty Ltd (ABN 77 084 670 600)
|
||||
* @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
|
||||
* @version Release: 1.3.3
|
||||
* @link http://pear.php.net/package/PHP_CodeSniffer
|
||||
*/
|
||||
class MySource_Sniffs_Channels_DisallowSelfActionsSniff implements PHP_CodeSniffer_Sniff
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Returns an array of tokens this test wants to listen for.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
return array(T_CLASS);
|
||||
|
||||
}//end register()
|
||||
|
||||
|
||||
/**
|
||||
* Processes this sniff, when one of its tokens is encountered.
|
||||
*
|
||||
* @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(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
|
||||
{
|
||||
$tokens = $phpcsFile->getTokens();
|
||||
|
||||
// We are not interested in abstract classes.
|
||||
$prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
|
||||
if ($prev !== false && $tokens[$prev]['code'] === T_ABSTRACT) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We are only interested in Action classes.
|
||||
$classNameToken = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
|
||||
$className = $tokens[$classNameToken]['content'];
|
||||
if (substr($className, -7) !== 'Actions') {
|
||||
return;
|
||||
}
|
||||
|
||||
$foundFunctions = array();
|
||||
$foundCalls = array();
|
||||
|
||||
// Find all static method calls in the form self::method() in the class.
|
||||
$classEnd = $tokens[$stackPtr]['scope_closer'];
|
||||
for ($i = ($classNameToken + 1); $i < $classEnd; $i++) {
|
||||
if ($tokens[$i]['code'] !== T_DOUBLE_COLON) {
|
||||
if ($tokens[$i]['code'] === T_FUNCTION) {
|
||||
// Cache the function information.
|
||||
$funcName = $phpcsFile->findNext(T_STRING, ($i + 1));
|
||||
$funcScope = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$scopeModifiers, ($i - 1));
|
||||
|
||||
$foundFunctions[$tokens[$funcName]['content']] = strtolower($tokens[$funcScope]['content']);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$prevToken = $phpcsFile->findPrevious(T_WHITESPACE, ($i - 1), null, true);
|
||||
if ($tokens[$prevToken]['content'] !== 'self') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$funcNameToken = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), null, true);
|
||||
if ($tokens[$funcNameToken]['code'] === T_VARIABLE) {
|
||||
// We are only interested in function calls.
|
||||
continue;
|
||||
}
|
||||
|
||||
$funcName = $tokens[$funcNameToken]['content'];
|
||||
|
||||
// We've found the function, now we need to find it and see if it is
|
||||
// public, private or protected. If it starts with an underscore we
|
||||
// can assume it is private.
|
||||
if ($funcName{0} === '_') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$foundCalls[$i] = $funcName;
|
||||
}//end for
|
||||
|
||||
$errorClassName = substr($className, 0, -7);
|
||||
|
||||
foreach ($foundCalls as $token => $funcName) {
|
||||
if (isset($foundFunctions[$funcName]) === false) {
|
||||
// Function was not in this class, might have come from the parent.
|
||||
// Either way, we can't really check this.
|
||||
continue;
|
||||
} else if ($foundFunctions[$funcName] === 'public') {
|
||||
$error = 'Static calls to public methods in Action classes must not use the self keyword; use %s::%s() instead';
|
||||
$data = array(
|
||||
$errorClassName,
|
||||
$funcName,
|
||||
);
|
||||
$phpcsFile->addError($error, $token, 'Found', $data);
|
||||
}
|
||||
}
|
||||
|
||||
}//end process()
|
||||
|
||||
|
||||
}//end class
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,329 @@
|
||||
<?php
|
||||
/**
|
||||
* Ensures that systems, asset types and libs are included before they are used.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category PHP
|
||||
* @package PHP_CodeSniffer_MySource
|
||||
* @author Greg Sherwood <gsherwood@squiz.net>
|
||||
* @copyright 2006-2011 Squiz Pty Ltd (ABN 77 084 670 600)
|
||||
* @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
|
||||
* @link http://pear.php.net/package/PHP_CodeSniffer
|
||||
*/
|
||||
|
||||
if (class_exists('PHP_CodeSniffer_Standards_AbstractScopeSniff', true) === false) {
|
||||
$error = 'Class PHP_CodeSniffer_Standards_AbstractScopeSniff not found';
|
||||
throw new PHP_CodeSniffer_Exception($error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that systems, asset types and libs are included before they are used.
|
||||
*
|
||||
* @category PHP
|
||||
* @package PHP_CodeSniffer_MySource
|
||||
* @author Greg Sherwood <gsherwood@squiz.net>
|
||||
* @copyright 2006-2011 Squiz Pty Ltd (ABN 77 084 670 600)
|
||||
* @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
|
||||
* @version Release: 1.3.3
|
||||
* @link http://pear.php.net/package/PHP_CodeSniffer
|
||||
*/
|
||||
class MySource_Sniffs_Channels_IncludeSystemSniff extends PHP_CodeSniffer_Standards_AbstractScopeSniff
|
||||
{
|
||||
|
||||
/**
|
||||
* A list of classes that don't need to be included.
|
||||
*
|
||||
* @var array(string)
|
||||
*/
|
||||
private $_ignore = array(
|
||||
'self',
|
||||
'parent',
|
||||
'channels',
|
||||
'basesystem',
|
||||
'dal',
|
||||
'init',
|
||||
'pdo',
|
||||
'util',
|
||||
'ziparchive',
|
||||
'phpunit_framework_assert',
|
||||
'abstractmysourceunittest',
|
||||
'abstractdatacleanunittest',
|
||||
'exception',
|
||||
'abstractwidgetwidgettype',
|
||||
'domdocument',
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a Squiz_Sniffs_Scope_MethodScopeSniff.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(array(T_FUNCTION), array(T_DOUBLE_COLON, T_EXTENDS), true);
|
||||
|
||||
}//end __construct()
|
||||
|
||||
|
||||
/**
|
||||
* Processes the function tokens within the class.
|
||||
*
|
||||
* @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
|
||||
* @param integer $stackPtr The position where the token was found.
|
||||
* @param integer $currScope The current scope opener token.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function processTokenWithinScope(
|
||||
PHP_CodeSniffer_File $phpcsFile,
|
||||
$stackPtr,
|
||||
$currScope
|
||||
) {
|
||||
$tokens = $phpcsFile->getTokens();
|
||||
|
||||
// Determine the name of the class that the static function
|
||||
// is being called on.
|
||||
$classNameToken = $phpcsFile->findPrevious(
|
||||
T_WHITESPACE,
|
||||
($stackPtr - 1),
|
||||
null,
|
||||
true
|
||||
);
|
||||
|
||||
$className = $tokens[$classNameToken]['content'];
|
||||
if (in_array(strtolower($className), $this->_ignore) === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
$includedClasses = array();
|
||||
|
||||
$fileName = strtolower($phpcsFile->getFilename());
|
||||
$matches = array();
|
||||
if (preg_match('|/systems/(.*)/([^/]+)?actions.inc$|', $fileName, $matches) !== 0) {
|
||||
// This is an actions file, which means we don't
|
||||
// have to include the system in which it exists.
|
||||
$includedClasses[] = $matches[2];
|
||||
|
||||
// Or a system it implements.
|
||||
$class = $phpcsFile->getCondition($stackPtr, T_CLASS);
|
||||
$implements = $phpcsFile->findNext(T_IMPLEMENTS, $class, ($class + 10));
|
||||
if ($implements !== false) {
|
||||
$implementsClass = $phpcsFile->findNext(T_STRING, $implements);
|
||||
$implementsClassName = strtolower($tokens[$implementsClass]['content']);
|
||||
if (substr($implementsClassName, -7) === 'actions') {
|
||||
$includedClasses[] = substr($implementsClassName, 0, -7);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Go searching for includeSystem and includeAsset calls within this
|
||||
// function, or the inclusion of .inc files, which
|
||||
// would be library files.
|
||||
for ($i = ($currScope + 1); $i < $stackPtr; $i++) {
|
||||
$name = $this->getIncludedClassFromToken($phpcsFile, $tokens, $i);
|
||||
if ($name !== false) {
|
||||
$includedClasses[] = $name;
|
||||
// Special case for Widgets cause they are, well, special.
|
||||
} else if (strtolower($tokens[$i]['content']) === 'includewidget') {
|
||||
$typeName = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($i + 1));
|
||||
$typeName = trim($tokens[$typeName]['content'], " '");
|
||||
$includedClasses[] = strtolower($typeName).'widgettype';
|
||||
}
|
||||
}
|
||||
|
||||
// Now go searching for includeSystem, includeAsset or require/include
|
||||
// calls outside our scope. If we are in a class, look outside the
|
||||
// class. If we are not, look outside the function.
|
||||
$condPtr = $currScope;
|
||||
if ($phpcsFile->hasCondition($stackPtr, T_CLASS) === true) {
|
||||
foreach ($tokens[$stackPtr]['conditions'] as $condPtr => $condType) {
|
||||
if ($condType === T_CLASS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ($i = 0; $i < $condPtr; $i++) {
|
||||
// Skip other scopes.
|
||||
if (isset($tokens[$i]['scope_closer']) === true) {
|
||||
$i = $tokens[$i]['scope_closer'];
|
||||
continue;
|
||||
}
|
||||
|
||||
$name = $this->getIncludedClassFromToken($phpcsFile, $tokens, $i);
|
||||
if ($name !== false) {
|
||||
$includedClasses[] = $name;
|
||||
}
|
||||
}//end for
|
||||
|
||||
// If we are in a testing class, we might have also included
|
||||
// some systems and classes in our setUp() method.
|
||||
$setupFunction = null;
|
||||
if ($phpcsFile->hasCondition($stackPtr, T_CLASS) === true) {
|
||||
foreach ($tokens[$stackPtr]['conditions'] as $condPtr => $condType) {
|
||||
if ($condType === T_CLASS) {
|
||||
// Is this is a testing class?
|
||||
$name = $phpcsFile->findNext(T_STRING, $condPtr);
|
||||
$name = $tokens[$name]['content'];
|
||||
if (substr($name, -8) === 'UnitTest') {
|
||||
// Look for a method called setUp().
|
||||
$end = $tokens[$condPtr]['scope_closer'];
|
||||
$function = $phpcsFile->findNext(T_FUNCTION, ($condPtr + 1), $end);
|
||||
while ($function !== false) {
|
||||
$name = $phpcsFile->findNext(T_STRING, $function);
|
||||
if ($tokens[$name]['content'] === 'setUp') {
|
||||
$setupFunction = $function;
|
||||
break;
|
||||
}
|
||||
|
||||
$function = $phpcsFile->findNext(T_FUNCTION, ($function + 1), $end);
|
||||
}
|
||||
}
|
||||
}
|
||||
}//end foreach
|
||||
}//end if
|
||||
|
||||
if ($setupFunction !== null) {
|
||||
$start = ($tokens[$setupFunction]['scope_opener'] + 1);
|
||||
$end = $tokens[$setupFunction]['scope_closer'];
|
||||
for ($i = $start; $i < $end; $i++) {
|
||||
$name = $this->getIncludedClassFromToken($phpcsFile, $tokens, $i);
|
||||
if ($name !== false) {
|
||||
$includedClasses[] = $name;
|
||||
}
|
||||
}
|
||||
}//end if
|
||||
|
||||
if (in_array(strtolower($className), $includedClasses) === false) {
|
||||
$error = 'Static method called on non-included class or system "%s"; include system with Channels::includeSystem() or include class with require_once';
|
||||
$data = array($className);
|
||||
$phpcsFile->addError($error, $stackPtr, 'NotIncludedCall', $data);
|
||||
}
|
||||
|
||||
}//end processTokenWithinScope()
|
||||
|
||||
|
||||
/**
|
||||
* Processes a token within the scope that this test is listening to.
|
||||
*
|
||||
* @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
|
||||
* @param int $stackPtr The position in the stack where
|
||||
* this token was found.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function processTokenOutsideScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
|
||||
{
|
||||
$tokens = $phpcsFile->getTokens();
|
||||
|
||||
if ($tokens[$stackPtr]['code'] === T_EXTENDS) {
|
||||
// Find the class name.
|
||||
$classNameToken = $phpcsFile->findNext(T_STRING, ($stackPtr + 1));
|
||||
$className = $tokens[$classNameToken]['content'];
|
||||
} else {
|
||||
// Determine the name of the class that the static function
|
||||
// is being called on.
|
||||
$classNameToken = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
|
||||
$className = $tokens[$classNameToken]['content'];
|
||||
}
|
||||
|
||||
// Some systems are always available.
|
||||
if (in_array(strtolower($className), $this->_ignore) === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
$includedClasses = array();
|
||||
|
||||
$fileName = strtolower($phpcsFile->getFilename());
|
||||
$matches = array();
|
||||
if (preg_match('|/systems/([^/]+)/([^/]+)?actions.inc$|', $fileName, $matches) !== 0) {
|
||||
// This is an actions file, which means we don't
|
||||
// have to include the system in which it exists
|
||||
// We know the system from the path.
|
||||
$includedClasses[] = $matches[1];
|
||||
}
|
||||
|
||||
// Go searching for includeSystem, includeAsset or require/include
|
||||
// calls outside our scope.
|
||||
for ($i = 0; $i < $stackPtr; $i++) {
|
||||
// Skip classes and functions as will we never get
|
||||
// into their scopes when including this file, although
|
||||
// we have a chance of getting into IF's, WHILE's etc.
|
||||
$ignoreTokens = array(
|
||||
T_CLASS,
|
||||
T_INTERFACE,
|
||||
T_FUNCTION,
|
||||
);
|
||||
|
||||
if (in_array($tokens[$i]['code'], $ignoreTokens) === true
|
||||
&& isset($tokens[$i]['scope_closer']) === true
|
||||
) {
|
||||
$i = $tokens[$i]['scope_closer'];
|
||||
continue;
|
||||
}
|
||||
|
||||
$name = $this->getIncludedClassFromToken($phpcsFile, $tokens, $i);
|
||||
if ($name !== false) {
|
||||
$includedClasses[] = $name;
|
||||
// Special case for Widgets cause they are, well, special.
|
||||
} else if (strtolower($tokens[$i]['content']) === 'includewidget') {
|
||||
$typeName = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($i + 1));
|
||||
$typeName = trim($tokens[$typeName]['content'], " '");
|
||||
$includedClasses[] = strtolower($typeName).'widgettype';
|
||||
}
|
||||
}//end for
|
||||
|
||||
if (in_array(strtolower($className), $includedClasses) === false) {
|
||||
if ($tokens[$stackPtr]['code'] === T_EXTENDS) {
|
||||
$error = 'Class extends non-included class or system "%s"; include system with Channels::includeSystem() or include class with require_once';
|
||||
$data = array($className);
|
||||
$phpcsFile->addError($error, $stackPtr, 'NotIncludedExtends', $data);
|
||||
} else {
|
||||
$error = 'Static method called on non-included class or system "%s"; include system with Channels::includeSystem() or include class with require_once';
|
||||
$data = array($className);
|
||||
$phpcsFile->addError($error, $stackPtr, 'NotIncludedCall', $data);
|
||||
}
|
||||
}
|
||||
|
||||
}//end processTokenOutsideScope()
|
||||
|
||||
|
||||
/**
|
||||
* Determines the included class name from given token.
|
||||
*
|
||||
* @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
|
||||
* @param array $tokens The array of file tokens.
|
||||
* @param int $stackPtr The position in the tokens array of the
|
||||
* potentially included class.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getIncludedClassFromToken(
|
||||
PHP_CodeSniffer_File $phpcsFile,
|
||||
array $tokens,
|
||||
$stackPtr
|
||||
) {
|
||||
if (strtolower($tokens[$stackPtr]['content']) === 'includesystem') {
|
||||
$systemName = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($stackPtr + 1));
|
||||
$systemName = trim($tokens[$systemName]['content'], " '");
|
||||
return strtolower($systemName);
|
||||
} else if (strtolower($tokens[$stackPtr]['content']) === 'includeasset') {
|
||||
$typeName = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($stackPtr + 1));
|
||||
$typeName = trim($tokens[$typeName]['content'], " '");
|
||||
return strtolower($typeName).'assettype';
|
||||
} else if (in_array($tokens[$stackPtr]['code'], PHP_CodeSniffer_Tokens::$includeTokens) === true) {
|
||||
$filePath = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($stackPtr + 1));
|
||||
$filePath = $tokens[$filePath]['content'];
|
||||
$filePath = trim($filePath, " '");
|
||||
$filePath = basename($filePath, '.inc');
|
||||
return strtolower($filePath);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}//end getIncludedClassFromToken()
|
||||
|
||||
|
||||
}//end class
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
/**
|
||||
* Ensures that systems, asset types and libs are included before they are used.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category PHP
|
||||
* @package PHP_CodeSniffer_MySource
|
||||
* @author Greg Sherwood <gsherwood@squiz.net>
|
||||
* @copyright 2006-2011 Squiz Pty Ltd (ABN 77 084 670 600)
|
||||
* @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
|
||||
* @link http://pear.php.net/package/PHP_CodeSniffer
|
||||
*/
|
||||
|
||||
/**
|
||||
* Ensures that systems and asset types are used if they are included.
|
||||
*
|
||||
* @category PHP
|
||||
* @package PHP_CodeSniffer_MySource
|
||||
* @author Greg Sherwood <gsherwood@squiz.net>
|
||||
* @copyright 2006-2011 Squiz Pty Ltd (ABN 77 084 670 600)
|
||||
* @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
|
||||
* @version Release: 1.3.3
|
||||
* @link http://pear.php.net/package/PHP_CodeSniffer
|
||||
*/
|
||||
class MySource_Sniffs_Channels_UnusedSystemSniff implements PHP_CodeSniffer_Sniff
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Returns an array of tokens this test wants to listen for.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
return array(T_DOUBLE_COLON);
|
||||
|
||||
}//end register()
|
||||
|
||||
|
||||
/**
|
||||
* Processes this sniff, when one of its tokens is encountered.
|
||||
*
|
||||
* @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(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
|
||||
{
|
||||
$tokens = $phpcsFile->getTokens();
|
||||
|
||||
// Check if this is a call to includeSystem, includeAsset or includeWidget.
|
||||
$methodName = strtolower($tokens[($stackPtr + 1)]['content']);
|
||||
if (in_array($methodName, array('includesystem', 'includeasset', 'includewidget')) === true) {
|
||||
$systemName = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 3), null, true);
|
||||
if ($systemName === false || $tokens[$systemName]['code'] !== T_CONSTANT_ENCAPSED_STRING) {
|
||||
// Must be using a variable instead of a specific system name.
|
||||
// We can't accurately check that.
|
||||
return;
|
||||
}
|
||||
|
||||
$systemName = trim($tokens[$systemName]['content'], " '");
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($methodName === 'includeasset') {
|
||||
$systemName .= 'assettype';
|
||||
} else if ($methodName === 'includewidget') {
|
||||
$systemName .= 'widgettype';
|
||||
}
|
||||
|
||||
$systemName = strtolower($systemName);
|
||||
|
||||
// Now check if this system is used anywhere in this scope.
|
||||
$level = $tokens[$stackPtr]['level'];
|
||||
for ($i = ($stackPtr + 1); $i < $phpcsFile->numTokens; $i++) {
|
||||
if ($tokens[$i]['level'] < $level) {
|
||||
// We have gone out of scope.
|
||||
// If the original include was inside an IF statement that
|
||||
// is checking if the system exists, check the outer scope
|
||||
// as well.
|
||||
if ($tokens[$stackPtr]['level'] === $level) {
|
||||
// We are still in the base level, so this is the first
|
||||
// time we have got here.
|
||||
$conditions = array_keys($tokens[$stackPtr]['conditions']);
|
||||
if (empty($conditions) === false) {
|
||||
$cond = array_pop($conditions);
|
||||
if ($tokens[$cond]['code'] === T_IF) {
|
||||
$i = $tokens[$cond]['scope_closer'];
|
||||
$level--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}//end if
|
||||
|
||||
$validTokens = array(
|
||||
T_DOUBLE_COLON,
|
||||
T_EXTENDS,
|
||||
T_IMPLEMENTS,
|
||||
);
|
||||
|
||||
if (in_array($tokens[$i]['code'], $validTokens) === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch ($tokens[$i]['code']) {
|
||||
case T_DOUBLE_COLON:
|
||||
$usedName = strtolower($tokens[($i - 1)]['content']);
|
||||
if ($usedName === $systemName) {
|
||||
// The included system was used, so it is fine.
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
case T_EXTENDS:
|
||||
$classNameToken = $phpcsFile->findNext(T_STRING, ($i + 1));
|
||||
$className = strtolower($tokens[$classNameToken]['content']);
|
||||
if ($className === $systemName) {
|
||||
// The included system was used, so it is fine.
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
case T_IMPLEMENTS:
|
||||
$endImplements = $phpcsFile->findNext(array(T_EXTENDS, T_OPEN_CURLY_BRACKET), ($i + 1));
|
||||
for ($x = ($i + 1); $x < $endImplements; $x++) {
|
||||
if ($tokens[$x]['code'] === T_STRING) {
|
||||
$className = strtolower($tokens[$x]['content']);
|
||||
if ($className === $systemName) {
|
||||
// The included system was used, so it is fine.
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}//end switch
|
||||
}//end for
|
||||
|
||||
// If we get to here, the system was not use.
|
||||
$error = 'Included system "%s" is never used';
|
||||
$data = array($systemName);
|
||||
$phpcsFile->addError($error, $stackPtr, 'Found', $data);
|
||||
|
||||
}//end process()
|
||||
|
||||
|
||||
}//end class
|
||||
|
||||
?>
|
||||
Reference in New Issue
Block a user