PHP_CodeSniffer
[ class tree: PHP_CodeSniffer ] [ index: PHP_CodeSniffer ] [ all elements ]

Source for file ForbiddenFunctionsSniff.php

Documentation is available at ForbiddenFunctionsSniff.php

  1. <?php
  2. /**
  3.  * Discourages the use of alias functions.
  4.  *
  5.  * Alias functions are kept in PHP for compatibility
  6.  * with older versions. Can be used to forbid the use of any function.
  7.  *
  8.  * @author    Greg Sherwood <gsherwood@squiz.net>
  9.  * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
  10.  * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
  11.  */
  12.  
  13. namespace PHP_CodeSniffer\Standards\Generic\Sniffs\PHP;
  14.  
  15. use PHP_CodeSniffer\Sniffs\Sniff;
  16. use PHP_CodeSniffer\Files\File;
  17.  
  18. class ForbiddenFunctionsSniff implements Sniff
  19. {
  20.  
  21.     /**
  22.      * A list of forbidden functions with their alternatives.
  23.      *
  24.      * The value is NULL if no alternative exists. IE, the
  25.      * function should just not be used.
  26.      *
  27.      * @var array<string, string|null>
  28.      */
  29.     public $forbiddenFunctions = array(
  30.                                   'sizeof' => 'count',
  31.                                   'delete' => 'unset',
  32.                                  );
  33.  
  34.     /**
  35.      * A cache of forbidden function names, for faster lookups.
  36.      *
  37.      * @var string[] 
  38.      */
  39.     protected $forbiddenFunctionNames = array();
  40.  
  41.     /**
  42.      * If true, forbidden functions will be considered regular expressions.
  43.      *
  44.      * @var boolean 
  45.      */
  46.     protected $patternMatch = false;
  47.  
  48.     /**
  49.      * If true, an error will be thrown; otherwise a warning.
  50.      *
  51.      * @var boolean 
  52.      */
  53.     public $error = true;
  54.  
  55.  
  56.     /**
  57.      * Returns an array of tokens this test wants to listen for.
  58.      *
  59.      * @return array 
  60.      */
  61.     public function register()
  62.     {
  63.         // Everyone has had a chance to figure out what forbidden functions
  64.         // they want to check for, so now we can cache out the list.
  65.         $this->forbiddenFunctionNames array_keys($this->forbiddenFunctions);
  66.  
  67.         if ($this->patternMatch === true{
  68.             foreach ($this->forbiddenFunctionNames as $i => $name{
  69.                 $this->forbiddenFunctionNames[$i'/'.$name.'/i';
  70.             }
  71.  
  72.             return array(T_STRING);
  73.         }
  74.  
  75.         // If we are not pattern matching, we need to work out what
  76.         // tokens to listen for.
  77.         $string '<?php ';
  78.         foreach ($this->forbiddenFunctionNames as $name{
  79.             $string .= $name.'();';
  80.         }
  81.  
  82.         $register = array();
  83.  
  84.         $tokens token_get_all($string);
  85.         array_shift($tokens);
  86.         foreach ($tokens as $token{
  87.             if (is_array($token=== true{
  88.                 $register[$token[0];
  89.             }
  90.         }
  91.  
  92.         $this->forbiddenFunctionNames array_map('strtolower'$this->forbiddenFunctionNames);
  93.         $this->forbiddenFunctions     array_combine($this->forbiddenFunctionNames$this->forbiddenFunctions);
  94.  
  95.         return array_unique($register);
  96.  
  97.     }//end register()
  98.  
  99.  
  100.     /**
  101.      * Processes this test, when one of its tokens is encountered.
  102.      *
  103.      * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned.
  104.      * @param int                         $stackPtr  The position of the current token in
  105.      *                                                the stack passed in $tokens.
  106.      *
  107.      * @return void 
  108.      */
  109.     public function process(File $phpcsFile$stackPtr)
  110.     {
  111.         $tokens $phpcsFile->getTokens();
  112.  
  113.         $ignore = array(
  114.                    T_DOUBLE_COLON    => true,
  115.                    T_OBJECT_OPERATOR => true,
  116.                    T_FUNCTION        => true,
  117.                    T_CONST           => true,
  118.                    T_PUBLIC          => true,
  119.                    T_PRIVATE         => true,
  120.                    T_PROTECTED       => true,
  121.                    T_AS              => true,
  122.                    T_NEW             => true,
  123.                    T_INSTEADOF       => true,
  124.                    T_NS_SEPARATOR    => true,
  125.                    T_IMPLEMENTS      => true,
  126.                   );
  127.  
  128.         $prevToken $phpcsFile->findPrevious(T_WHITESPACE($stackPtr - 1)nulltrue);
  129.  
  130.         // If function call is directly preceded by a NS_SEPARATOR it points to the
  131.         // global namespace, so we should still catch it.
  132.         if ($tokens[$prevToken]['code'=== T_NS_SEPARATOR{
  133.             $prevToken $phpcsFile->findPrevious(T_WHITESPACE($prevToken - 1)nulltrue);
  134.             if ($tokens[$prevToken]['code'=== T_STRING{
  135.                 // Not in the global namespace.
  136.                 return;
  137.             }
  138.         }
  139.  
  140.         if (isset($ignore[$tokens[$prevToken]['code']]=== true{
  141.             // Not a call to a PHP function.
  142.             return;
  143.         }
  144.  
  145.         $nextToken $phpcsFile->findNext(T_WHITESPACE($stackPtr + 1)nulltrue);
  146.         if (isset($ignore[$tokens[$nextToken]['code']]=== true{
  147.             // Not a call to a PHP function.
  148.             return;
  149.         }
  150.  
  151.         if ($tokens[$stackPtr]['code'=== T_STRING && $tokens[$nextToken]['code'!== T_OPEN_PARENTHESIS{
  152.             // Not a call to a PHP function.
  153.             return;
  154.         }
  155.  
  156.         $function strtolower($tokens[$stackPtr]['content']);
  157.         $pattern  = null;
  158.  
  159.         if ($this->patternMatch === true{
  160.             $count   = 0;
  161.             $pattern preg_replace(
  162.                 $this->forbiddenFunctionNames,
  163.                 $this->forbiddenFunctionNames,
  164.                 $function,
  165.                 1,
  166.                 $count
  167.             );
  168.  
  169.             if ($count === 0{
  170.                 return;
  171.             }
  172.  
  173.             // Remove the pattern delimiters and modifier.
  174.             $pattern substr($pattern1-2);
  175.         else {
  176.             if (in_array($function$this->forbiddenFunctionNames=== false{
  177.                 return;
  178.             }
  179.         }//end if
  180.  
  181.         $this->addError($phpcsFile$stackPtr$tokens[$stackPtr]['content']$pattern);
  182.  
  183.     }//end process()
  184.  
  185.  
  186.     /**
  187.      * Generates the error or warning for this sniff.
  188.      *
  189.      * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned.
  190.      * @param int                         $stackPtr  The position of the forbidden function
  191.      *                                                in the token array.
  192.      * @param string                      $function  The name of the forbidden function.
  193.      * @param string                      $pattern   The pattern used for the match.
  194.      *
  195.      * @return void 
  196.      */
  197.     protected function addError($phpcsFile$stackPtr$function$pattern=null)
  198.     {
  199.         $data  = array($function);
  200.         $error 'The use of function %s() is ';
  201.         if ($this->error === true{
  202.             $type   'Found';
  203.             $error .= 'forbidden';
  204.         else {
  205.             $type   'Discouraged';
  206.             $error .= 'discouraged';
  207.         }
  208.  
  209.         if ($pattern === null{
  210.             $pattern strtolower($function);
  211.         }
  212.  
  213.         if ($this->forbiddenFunctions[$pattern!== null
  214.             && $this->forbiddenFunctions[$pattern!== 'null'
  215.         {
  216.             $type  .= 'WithAlternative';
  217.             $data[$this->forbiddenFunctions[$pattern];
  218.             $error .= '; use %s() instead';
  219.         }
  220.  
  221.         if ($this->error === true{
  222.             $phpcsFile->addError($error$stackPtr$type$data);
  223.         else {
  224.             $phpcsFile->addWarning($error$stackPtr$type$data);
  225.         }
  226.  
  227.     }//end addError()
  228.  
  229.  
  230. }//end class

Documentation generated on Mon, 11 Mar 2019 15:27:29 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.