Initial Commit

This commit is contained in:
Riley Schneider
2025-12-03 16:38:10 +01:00
parent c5e26bf594
commit b732d8d4b5
17680 changed files with 5977495 additions and 2 deletions

View File

@@ -0,0 +1,102 @@
<?php
/**
* MySource_Sniffs_CSS_BrowserSpecificStylesSniff.
*
* PHP version 5
*
* @category PHP
* @package PHP_CodeSniffer
* @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
*/
/**
* MySource_Sniffs_CSS_BrowserSpecificStylesSniff.
*
* Ensure that browser-specific styles are not used.
*
* @category PHP
* @package PHP_CodeSniffer
* @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_CSS_BrowserSpecificStylesSniff implements PHP_CodeSniffer_Sniff
{
/**
* A list of tokenizers this sniff supports.
*
* @var array
*/
public $supportedTokenizers = array('CSS');
/**
* A list of specific stylsheet suffixes we allow.
*
* These stylsheets contain browser specific styles
* so this sniff ignore them files in the form:
* *_moz.css and *_ie7.css etc.
*
* @var array
*/
protected $specificStylesheets = array(
'moz',
'ie',
'ie7',
'ie8',
'webkit',
);
/**
* Returns the token types that this sniff is interested in.
*
* @return array(int)
*/
public function register()
{
return array(T_STYLE);
}//end register()
/**
* Processes the tokens that this sniff is interested in.
*
* @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
* @param int $stackPtr The position in the stack where
* the token was found.
*
* @return void
*/
public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
{
// Ignore files with browser-specific suffixes.
$filename = $phpcsFile->getFilename();
$breakChar = strrpos($filename, '_');
if ($breakChar !== false && substr($filename, -4) === '.css') {
$specific = substr($filename, ($breakChar + 1), -4);
if (in_array($specific, $this->specificStylesheets) === true) {
return;
}
}
$tokens = $phpcsFile->getTokens();
$content = $tokens[$stackPtr]['content'];
if ($content{0} === '-') {
$error = 'Browser-specific styles are not allowed';
$phpcsFile->addError($error, $stackPtr, 'ForbiddenStyle');
}
}//end process()
}//end class
?>

View File

@@ -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
?>

View File

@@ -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
?>

View File

@@ -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
?>

View File

@@ -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
?>

View File

@@ -0,0 +1,134 @@
<?php
/**
* Parses and verifies the doc comments for functions.
*
* PHP version 5
*
* @category PHP
* @package PHP_CodeSniffer
* @author Greg Sherwood <gsherwood@squiz.net>
* @author Marc McIntyre <mmcintyre@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('Squiz_Sniffs_Commenting_FunctionCommentSniff', true) === false) {
$error = 'Class Squiz_Sniffs_Commenting_FunctionCommentSniff not found';
throw new PHP_CodeSniffer_Exception($error);
}
/**
* Parses and verifies the doc comments for functions.
*
* Same as the Squiz standard, but adds support for API tags.
*
* @category PHP
* @package PHP_CodeSniffer
* @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_Commenting_FunctionCommentSniff extends Squiz_Sniffs_Commenting_FunctionCommentSniff
{
/**
* Process a list of unknown tags.
*
* @param int $commentStart The position in the stack where the comment started.
* @param int $commentEnd The position in the stack where the comment ended.
*
* @return void
*/
protected function processUnknownTags($commentStart, $commentEnd)
{
$unknownTags = $this->commentParser->getUnknown();
$words = $this->commentParser->getWords();
$hasApiTag = false;
$apiLength = 3;
foreach ($unknownTags as $errorTag) {
$pos = $errorTag['pos'];
if ($errorTag['tag'] === 'api') {
if ($hasApiTag === true) {
// We've come across an API tag already, which means
// we were not the first tag in the API list.
$error = 'The @api tag must come first in the @api tag list in a function comment';
$this->currentFile->addError($error, ($commentStart + $errorTag['line']), 'ApiNotFirst');
}
$hasApiTag = true;
// There needs to be a blank line before the @api tag.
// So expect a single space before the tag, then 2 newlines before
// that, then some content.
if (trim($words[($pos - 2)]) !== ''
|| strpos($words[($pos - 2)], $this->currentFile->eolChar) === false
|| strpos($words[($pos - 3)], $this->currentFile->eolChar) === false
|| trim($words[($pos - 4)]) === ''
) {
$error = 'There must be one blank line before the @api tag in a function comment';
$this->currentFile->addError($error, ($commentStart + $errorTag['line']), 'ApiSpacing');
}
} else if (substr($errorTag['tag'], 0, 4) === 'api-') {
$hasApiTag = true;
$tagLength = strlen($errorTag['tag']);
if ($tagLength > $apiLength) {
$apiLength = $tagLength;
}
if (trim($words[($pos - 2)]) !== ''
|| strpos($words[($pos - 2)], $this->currentFile->eolChar) === false
|| trim($words[($pos - 3)]) === ''
) {
$error = 'There must be no blank line before the @%s tag in a function comment';
$data = array($errorTag['tag']);
$this->currentFile->addError($error, ($commentStart + $errorTag['line']), 'ApiTagSpacing', $data);
}
} else {
$error = '@%s tag is not allowed in function comment';
$data = array($errorTag['tag']);
$this->currentFile->addWarning($error, ($commentStart + $errorTag['line']), 'TagNotAllowed', $data);
}//end if
}//end foreach
if ($hasApiTag === true) {
// API tags must be the last tags in a function comment.
$order = $this->commentParser->getTagOrders();
$lastTag = array_pop($order);
if ($lastTag !== 'api'
&& substr($lastTag, 0, 4) !== 'api-'
) {
$error = 'The @api tags must be the last tags in a function comment';
$this->currentFile->addError($error, $commentEnd, 'ApiNotLast');
}
// Check API tag indenting.
foreach ($unknownTags as $errorTag) {
if ($errorTag['tag'] === 'api'
|| substr($errorTag['tag'], 0, 4) === 'api-'
) {
$expected = ($apiLength - strlen($errorTag['tag']) + 1);
$found = strlen($words[($errorTag['pos'] + 1)]);
if ($found !== $expected) {
$error = '@%s tag indented incorrectly; expected %s spaces but found %s';
$data = array(
$errorTag['tag'],
$expected,
$found,
);
$this->currentFile->addError($error, ($commentStart + $errorTag['line']), 'ApiTagIndent', $data);
}
}
}
}//end if
}//end processUnknownTags()
}//end class
?>

View File

@@ -0,0 +1,68 @@
<?php
/**
* Warns about the use of debug code.
*
* 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
*/
/**
* Warns about the use of debug code.
*
* @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_Debug_DebugCodeSniff 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();
$className = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
if (strtolower($tokens[$className]['content']) === 'debug') {
$method = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
$error = 'Call to debug function Debug::%s() must be removed';
$data = array($tokens[$method]['content']);
$phpcsFile->addError($error, $stackPtr, 'Found', $data);
}
}//end process()
}//end class
?>

View File

@@ -0,0 +1,77 @@
<?php
/**
* Ensures that console is not used for function or var names.
*
* 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 console is not used for function or var names.
*
* @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_Debug_FirebugConsoleSniff implements PHP_CodeSniffer_Sniff
{
/**
* A list of tokenizers this sniff supports.
*
* @var array
*/
public $supportedTokenizers = array('JS');
/**
* Returns an array of tokens this test wants to listen for.
*
* @return array
*/
public function register()
{
return array(
T_STRING,
T_PROPERTY,
T_LABEL,
T_OBJECT,
);
}//end register()
/**
* Processes this test, 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();
if (strtolower($tokens[$stackPtr]['content']) === 'console') {
$error = 'Variables, functions and labels must not be named "console"; name may conflict with Firebug internal variable';
$phpcsFile->addError($error, $stackPtr, 'ConflictFound');
}
}//end process()
}//end class
?>

View File

@@ -0,0 +1,94 @@
<?php
/**
* Ensures this is not assigned to any other var but self.
*
* 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 this is not assigned to any other var but self.
*
* @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_Objects_AssignThisSniff implements PHP_CodeSniffer_Sniff
{
/**
* A list of tokenizers this sniff supports.
*
* @var array
*/
public $supportedTokenizers = array('JS');
/**
* Returns an array of tokens this test wants to listen for.
*
* @return array
*/
public function register()
{
return array(T_THIS);
}//end register()
/**
* Processes this test, 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();
// Ignore this.something and other uses of "this" that are not
// direct assignments.
$next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
if ($tokens[$next]['code'] !== T_SEMICOLON) {
if ($tokens[$next]['line'] === $tokens[$stackPtr]['line']) {
return;
}
}
// Something must be assigned to "this".
$prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
if ($tokens[$prev]['code'] !== T_EQUAL) {
return;
}
// A variable needs to be assigned to "this".
$prev = $phpcsFile->findPrevious(T_WHITESPACE, ($prev - 1), null, true);
if ($tokens[$prev]['code'] !== T_STRING) {
return;
}
// We can only assign "this" to a var called "self".
if ($tokens[$prev]['content'] !== 'self' && $tokens[$prev]['content'] !== '_self') {
$error = 'Keyword "this" can only be assigned to a variable called "self" or "_self"';
$phpcsFile->addError($error, $prev, 'NotSelf');
}
}//end process()
}//end class
?>

View File

@@ -0,0 +1,228 @@
<?php
/**
* Ensures the create() method of widget types properly uses callbacks.
*
* 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 the create() method of widget types properly uses callbacks.
*
* @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_Objects_CreateWidgetTypeCallbackSniff implements PHP_CodeSniffer_Sniff
{
/**
* A list of tokenizers this sniff supports.
*
* @var array
*/
public $supportedTokenizers = array('JS');
/**
* Returns an array of tokens this test wants to listen for.
*
* @return array
*/
public function register()
{
return array(T_OBJECT);
}//end register()
/**
* Processes this test, 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();
$className = $tokens[$stackPtr]['content'];
if (substr(strtolower($className), -10) !== 'widgettype') {
return;
}
// Search for a create method.
$start = ($tokens[$stackPtr]['scope_opener'] + 1);
$end = ($tokens[$stackPtr]['scope_closer'] - 1);
$create = $phpcsFile->findNext(T_PROPERTY, $start, $end, null, 'create');
if ($create === false) {
return;
}
$function = $phpcsFile->findNext(array(T_WHITESPACE, T_COLON), ($create + 1), null, true);
if ($tokens[$function]['code'] !== T_FUNCTION) {
continue;
}
$start = ($tokens[$function]['scope_opener'] + 1);
$end = ($tokens[$function]['scope_closer'] - 1);
// Check that the first argument is called "callback".
$arg = $phpcsFile->findNext(T_WHITESPACE, ($tokens[$function]['parenthesis_opener'] + 1), null, true);
if ($tokens[$arg]['content'] !== 'callback') {
$error = 'The first argument of the create() method of a widget type must be called "callback"';
$phpcsFile->addError($error, $arg, 'FirstArgNotCallback');
}
/*
Look for return statements within the function. They cannot return
anything and must be preceeded by the callback.call() line. The
callback itself must contain "self" or "this" as the first argument
and there needs to be a call to the callback function somewhere
in the create method. All calls to the callback function must be
followed by a return statement or the end of the method.
*/
$foundCallback = false;
$passedCallback = false;
$nestedFunction = null;
for ($i = $start; $i <= $end; $i++) {
// Keep track of nested functions.
if ($nestedFunction !== null) {
if ($i === $nestedFunction) {
$nestedFunction = null;
continue;
}
} else if ($tokens[$i]['code'] === T_FUNCTION
&& isset($tokens[$i]['scope_closer']) === true
) {
$nestedFunction = $tokens[$i]['scope_closer'];
continue;
}
if ($nestedFunction === null && $tokens[$i]['code'] === T_RETURN) {
// Make sure return statements are not returning anything.
if ($tokens[($i + 1)]['code'] !== T_SEMICOLON) {
$error = 'The create() method of a widget type must not return a value';
$phpcsFile->addError($error, $i, 'ReturnValue');
}
continue;
} else if ($tokens[$i]['code'] !== T_STRING
|| $tokens[$i]['content'] !== 'callback'
) {
continue;
}
// If this is the form "callback.call(" then it is a call
// to the callback function.
if ($tokens[($i + 1)]['code'] !== T_OBJECT_OPERATOR
|| $tokens[($i + 2)]['content'] !== 'call'
|| $tokens[($i + 3)]['code'] !== T_OPEN_PARENTHESIS
) {
// One last chance; this might be the callback function
// being passed to another function, like this
// "this.init(something, callback, something)".
if (isset($tokens[$i]['nested_parenthesis']) === false) {
continue;
}
// Just make sure those brackets dont belong to anyone,
// like an IF or FOR statement.
foreach ($tokens[$i]['nested_parenthesis'] as $bracket) {
if (isset($tokens[$bracket]['parenthesis_owner']) === true) {
continue(2);
}
}
// Note that we use this endBracket down further when checking
// for a RETURN statement.
$endBracket = end($tokens[$i]['nested_parenthesis']);
$bracket = key($tokens[$i]['nested_parenthesis']);
$prev = $phpcsFile->findPrevious(
PHP_CodeSniffer_Tokens::$emptyTokens,
($bracket - 1),
null,
true
);
if ($tokens[$prev]['code'] !== T_STRING) {
// This is not a function passing the callback.
continue;
}
$passedCallback = true;
}//end if
$foundCallback = true;
if ($passedCallback === false) {
// The first argument must be "this" or "self".
$arg = $phpcsFile->findNext(T_WHITESPACE, ($i + 4), null, true);
if ($tokens[$arg]['content'] !== 'this'
&& $tokens[$arg]['content'] !== 'self'
) {
$error = 'The first argument passed to the callback function must be "this" or "self"';
$phpcsFile->addError($error, $arg, 'FirstArgNotSelf');
}
}
// Now it must be followed by a return statement or the end of the function.
if ($passedCallback === false) {
$endBracket = $tokens[($i + 3)]['parenthesis_closer'];
}
for ($next = $endBracket; $next <= $end; $next++) {
// Skip whitespace so we find the next content after the call.
if (in_array($tokens[$next]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === true) {
continue;
}
// Skip closing braces like END IF because it is not executable code.
if ($tokens[$next]['code'] === T_CLOSE_CURLY_BRACKET) {
continue;
}
// We don't care about anything on the current line, like a
// semicolon. It doesn't matter if there are other statements on the
// line because another sniff will check for those.
if ($tokens[$next]['line'] === $tokens[$endBracket]['line']) {
continue;
}
break;
}
if ($next !== $tokens[$function]['scope_closer']
&& $tokens[$next]['code'] !== T_RETURN
) {
$error = 'The call to the callback function must be followed by a return statement if it is not the last statement in the create() method';
$phpcsFile->addError($error, $i, 'NoReturn');
}
}//end for
if ($foundCallback === false) {
$error = 'The create() method of a widget type must call the callback function';
$phpcsFile->addError($error, $create, 'CallbackNotCalled');
}
}//end process()
}//end class
?>

View File

@@ -0,0 +1,72 @@
<?php
/**
* Ensures that widgets are not manually created.
*
* 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 widgets are not manually created.
*
* @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_Objects_DisallowNewWidgetSniff implements PHP_CodeSniffer_Sniff
{
/**
* Returns an array of tokens this test wants to listen for.
*
* @return array
*/
public function register()
{
return array(T_NEW);
}//end register()
/**
* Processes this test, 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();
$className = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
if ($tokens[$className]['code'] !== T_STRING) {
return;
}
if (substr(strtolower($tokens[$className]['content']), -10) === 'widgettype') {
$widgetType = substr($tokens[$className]['content'], 0, -10);
$error = 'Manual creation of widget objects is banned; use Widget::getWidget(\'%s\'); instead';
$data = array($widgetType);
$phpcsFile->addError($error, $stackPtr, 'Found', $data);
}
}//end process()
}//end class
?>

View File

@@ -0,0 +1,126 @@
<?php
/**
* Ensures that eval() is not used to create objects.
*
* 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 eval() is not used to create objects.
*
* @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_PHP_EvalObjectFactorySniff implements PHP_CodeSniffer_Sniff
{
/**
* Returns an array of tokens this test wants to listen for.
*
* @return array
*/
public function register()
{
return array(T_EVAL);
}//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 need to find all strings that will be in the eval
to determine if the "new" keyword is being used.
*/
$openBracket = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($stackPtr + 1));
$closeBracket = $tokens[$openBracket]['parenthesis_closer'];
$strings = array();
$vars = array();
for ($i = ($openBracket + 1); $i < $closeBracket; $i++) {
if (in_array($tokens[$i]['code'], PHP_CodeSniffer_Tokens::$stringTokens) === true) {
$strings[$i] = $tokens[$i]['content'];
} else if ($tokens[$i]['code'] === T_VARIABLE) {
$vars[$i] = $tokens[$i]['content'];
}
}
/*
We now have some variables that we need to expand into
the strings that were assigned to them, if any.
*/
foreach ($vars as $varPtr => $varName) {
while (($prev = $phpcsFile->findPrevious(T_VARIABLE, ($varPtr - 1))) !== false) {
// Make sure this is an assignment of the variable. That means
// it will be the first thing on the line.
$prevContent = $phpcsFile->findPrevious(T_WHITESPACE, ($prev - 1), null, true);
if ($tokens[$prevContent]['line'] === $tokens[$prev]['line']) {
$varPtr = $prevContent;
continue;
}
if ($tokens[$prev]['content'] !== $varName) {
// This variable has a different name.
$varPtr = $prevContent;
continue;
}
// We found one.
break;
}//end while
if ($prev !== false) {
// Find all strings on the line.
$lineEnd = $phpcsFile->findNext(T_SEMICOLON, ($prev + 1));
for ($i = ($prev + 1); $i < $lineEnd; $i++) {
if (in_array($tokens[$i]['code'], PHP_CodeSniffer_Tokens::$stringTokens) === true) {
$strings[$i] = $tokens[$i]['content'];
}
}
}
}//end foreach
foreach ($strings as $string) {
// If the string has "new" in it, it is not allowed.
// We don't bother checking if the word "new" is echo'd
// because that is unlikely to happen. We assume the use
// of "new" is for object instantiation.
if (strstr($string, ' new ') !== false) {
$error = 'Do not use eval() to create objects dynamically; use reflection instead';
$phpcsFile->addWarning($error, $stackPtr, 'Found');
}
}
}//end process()
}//end class
?>

View File

@@ -0,0 +1,119 @@
<?php
/**
* Ensures that getRequestData() is used to access super globals.
*
* 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 getRequestData() is used to access super globals.
*
* @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_PHP_GetRequestDataSniff implements PHP_CodeSniffer_Sniff
{
/**
* Returns an array of tokens this test wants to listen for.
*
* @return array
*/
public function register()
{
return array(T_VARIABLE);
}//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();
$varName = $tokens[$stackPtr]['content'];
if ($varName !== '$_REQUEST'
&& $varName !== '$_GET'
&& $varName !== '$_POST'
&& $varName !== '$_FILES'
) {
return;
}
// The only place these super globals can be accessed directly is
// in the getRequestData() method of the Security class.
$inClass = false;
foreach ($tokens[$stackPtr]['conditions'] as $i => $type) {
if ($tokens[$i]['code'] === T_CLASS) {
$className = $phpcsFile->findNext(T_STRING, $i);
$className = $tokens[$className]['content'];
if (strtolower($className) === 'security') {
$inClass = true;
} else {
// We don't have nested classes.
break;
}
} else if ($inClass === true && $tokens[$i]['code'] === T_FUNCTION) {
$funcName = $phpcsFile->findNext(T_STRING, $i);
$funcName = $tokens[$funcName]['content'];
if (strtolower($funcName) === 'getrequestdata') {
// This is valid.
return;
} else {
// We don't have nested functions.
break;
}
}//end if
}//end foreach
// If we get to here, the super global was used incorrectly.
// First find out how it is being used.
$globalName = strtolower(substr($varName, 2));
$usedVar = '';
$openBracket = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
if ($tokens[$openBracket]['code'] === T_OPEN_SQUARE_BRACKET) {
$closeBracket = $tokens[$openBracket]['bracket_closer'];
$usedVar = $phpcsFile->getTokensAsString(($openBracket + 1), ($closeBracket - $openBracket - 1));
}
$type = 'SuperglobalAccessed';
$error = 'The %s super global must not be accessed directly; use Security::getRequestData(';
$data = array($varName);
if ($usedVar !== '') {
$type .= 'WithVar';
$error .= '%s, \'%s\'';
$data[] = $usedVar;
$data[] = $globalName;
}
$error .= ') instead';
$phpcsFile->addError($error, $stackPtr, $type, $data);
}//end process()
}//end class
?>

View File

@@ -0,0 +1,76 @@
<?php
/**
* Warns when function values are returned directly.
*
* 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
*/
/**
* Warns when function values are returned directly.
*
* @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_PHP_ReturnFunctionValueSniff implements PHP_CodeSniffer_Sniff
{
/**
* Returns an array of tokens this test wants to listen for.
*
* @return array
*/
public function register()
{
return array(T_RETURN);
}//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();
$functionName = $phpcsFile->findNext(T_STRING, ($stackPtr + 1), null, false, null, true);
while ($functionName !== false) {
// Check if this is really a function.
$bracket = $phpcsFile->findNext(T_WHITESPACE, ($functionName + 1), null, true);
if ($tokens[$bracket]['code'] !== T_OPEN_PARENTHESIS) {
// Not a function call.
$functionName = $phpcsFile->findNext(T_STRING, ($functionName + 1), null, false, null, true);
continue;
}
$error = 'The result of a function call should be assigned to a variable before being returned';
$phpcsFile->addWarning($error, $stackPtr, 'NotAssigned');
break;
}
}//end process()
}//end class
?>

View File

@@ -0,0 +1,88 @@
<?php
/**
* Ensures that strings are not joined using array.join().
*
* 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 strings are not joined using array.join().
*
* @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_Strings_JoinStringsSniff implements PHP_CodeSniffer_Sniff
{
/**
* A list of tokenizers this sniff supports.
*
* @var array
*/
public $supportedTokenizers = array('JS');
/**
* Returns an array of tokens this test wants to listen for.
*
* @return array
*/
public function register()
{
return array(T_STRING);
}//end register()
/**
* Processes this test, when one of its tokens is encountered.
*
* @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
* @param integer $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();
if ($tokens[$stackPtr]['content'] !== 'join') {
return;
}
$prev = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr - 1), null, true);
if ($tokens[$prev]['code'] !== T_OBJECT_OPERATOR) {
return;
}
$prev = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($prev - 1), null, true);
if ($tokens[$prev]['code'] === T_CLOSE_SQUARE_BRACKET) {
$opener = $tokens[$prev]['bracket_opener'];
if ($tokens[($opener - 1)]['code'] !== T_STRING) {
// This means the array is declared inline, like x = [a,b,c].join()
// and not elsewhere, like x = y[a].join()
// The first is not allowed while the second is.
$error = 'Joining strings using inline arrays is not allowed; use the + operator instead';
$phpcsFile->addError($error, $stackPtr, 'ArrayNotAllowed');
}
}
}//end process()
}//end class
?>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0"?>
<ruleset name="MySource">
<description>The MySource coding standard builds on the Squiz coding standard. Currently used for MySource Mini development.</description>
<exclude-pattern>*/Tests/*</exclude-pattern>
<exclude-pattern>*/Oven/*</exclude-pattern>
<exclude-pattern>*/data/*</exclude-pattern>
<exclude-pattern>DALConf.inc</exclude-pattern>
<!-- Include the whole Squiz standard except FunctionComment, which we override -->
<rule ref="Squiz">
<exclude name="Squiz.Commenting.FunctionComment"/>
</rule>
</ruleset>