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

Source for file Ruleset.php

Documentation is available at Ruleset.php

  1. <?php
  2. /**
  3.  * Stores the rules used to check and fix files.
  4.  *
  5.  * A ruleset object directly maps to a ruleset XML file.
  6.  *
  7.  * @author    Greg Sherwood <gsherwood@squiz.net>
  8.  * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
  9.  * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
  10.  */
  11.  
  12. namespace PHP_CodeSniffer;
  13.  
  14. use PHP_CodeSniffer\Util;
  15. use PHP_CodeSniffer\Exceptions\RuntimeException;
  16.  
  17. class Ruleset
  18. {
  19.  
  20.     /**
  21.      * The name of the coding standard being used.
  22.      *
  23.      * If a top-level standard includes other standards, or sniffs
  24.      * from other standards, only the name of the top-level standard
  25.      * will be stored in here.
  26.      *
  27.      * If multiple top-level standards are being loaded into
  28.      * a single ruleset object, this will store a comma separated list
  29.      * of the top-level standard names.
  30.      *
  31.      * @var string 
  32.      */
  33.     public $name '';
  34.  
  35.     /**
  36.      * A list of file paths for the ruleset files being used.
  37.      *
  38.      * @var string[] 
  39.      */
  40.     public $paths = array();
  41.  
  42.     /**
  43.      * A list of regular expressions used to ignore specific sniffs for files and folders.
  44.      *
  45.      * Is also used to set global exclude patterns.
  46.      * The key is the regular expression and the value is the type
  47.      * of ignore pattern (absolute or relative).
  48.      *
  49.      * @var array<string, string>
  50.      */
  51.     public $ignorePatterns = array();
  52.  
  53.     /**
  54.      * A list of regular expressions used to include specific sniffs for files and folders.
  55.      *
  56.      * The key is the sniff code and the value is an array with
  57.      * the key being a regular expression and the value is the type
  58.      * of ignore pattern (absolute or relative).
  59.      *
  60.      * @var array<string, array<string, string>>
  61.      */
  62.     public $includePatterns = array();
  63.  
  64.     /**
  65.      * An array of sniff objects that are being used to check files.
  66.      *
  67.      * The key is the fully qualified name of the sniff class
  68.      * and the value is the sniff object.
  69.      *
  70.      * @var array<string, \PHP_CodeSniffer\Sniff>
  71.      */
  72.     public $sniffs = array();
  73.  
  74.     /**
  75.      * A mapping of sniff codes to fully qualified class names.
  76.      *
  77.      * The key is the sniff code and the value
  78.      * is the fully qualified name of the sniff class.
  79.      *
  80.      * @var array<string, string>
  81.      */
  82.     public $sniffCodes = array();
  83.  
  84.     /**
  85.      * An array of token types and the sniffs that are listening for them.
  86.      *
  87.      * The key is the token name being listened for and the value
  88.      * is the sniff object.
  89.      *
  90.      * @var array<int, \PHP_CodeSniffer\Sniff>
  91.      */
  92.     public $tokenListeners = array();
  93.  
  94.     /**
  95.      * An array of rules from the ruleset.xml file.
  96.      *
  97.      * It may be empty, indicating that the ruleset does not override
  98.      * any of the default sniff settings.
  99.      *
  100.      * @var array<string, mixed>
  101.      */
  102.     public $ruleset = array();
  103.  
  104.     /**
  105.      * The directories that the processed rulesets are in.
  106.      *
  107.      * @var string[] 
  108.      */
  109.     protected $rulesetDirs = array();
  110.  
  111.     /**
  112.      * The config data for the run.
  113.      *
  114.      * @var \PHP_CodeSniffer\Config 
  115.      */
  116.     private $config = null;
  117.  
  118.  
  119.     /**
  120.      * Initialise the ruleset that the run will use.
  121.      *
  122.      * @param \PHP_CodeSniffer\Config $config The config data for the run.
  123.      *
  124.      * @return void 
  125.      */
  126.     public function __construct(Config $config)
  127.     {
  128.         // Ignore sniff restrictions if caching is on.
  129.         $restrictions = array();
  130.         $exclusions   = array();
  131.         if ($config->cache === false{
  132.             $restrictions $config->sniffs;
  133.             $exclusions   $config->exclude;
  134.         }
  135.  
  136.         $this->config $config;
  137.         $sniffs       = array();
  138.  
  139.         $standardPaths = array();
  140.         foreach ($config->standards as $standard{
  141.             $installed = Util\Standards::getInstalledStandardPath($standard);
  142.             if ($installed === null{
  143.                 $standard = Util\Common::realpath($standard);
  144.                 if (is_dir($standard=== true
  145.                     && is_file(Util\Common::realpath($standard.DIRECTORY_SEPARATOR.'ruleset.xml')) === true
  146.                 {
  147.                     $standard = Util\Common::realpath($standard.DIRECTORY_SEPARATOR.'ruleset.xml');
  148.                 }
  149.             else {
  150.                 $standard $installed;
  151.             }
  152.  
  153.             $standardPaths[$standard;
  154.         }
  155.  
  156.         if (defined('PHP_CODESNIFFER_IN_TESTS'=== true && empty($restrictions=== false{
  157.             // Should be one standard and one sniff being tested at a time.
  158.             $sniffs $this->expandRulesetReference($restrictions[0]dirname($standardPaths[0]));
  159.         else {
  160.             foreach ($standardPaths as $standard{
  161.                 $ruleset simplexml_load_string(file_get_contents($standard));
  162.                 if ($ruleset !== false{
  163.                     $standardName = (string) $ruleset['name'];
  164.                     if ($this->name !== ''{
  165.                         $this->name .= ', ';
  166.                     }
  167.  
  168.                     $this->name   .= $standardName;
  169.                     $this->paths[$standard;
  170.  
  171.                     // Allow autoloading of custom files inside this standard.
  172.                     if (isset($ruleset['namespace']=== true{
  173.                         $namespace = (string) $ruleset['namespace'];
  174.                     else {
  175.                         $namespace basename(dirname($standard));
  176.                     }
  177.  
  178.                     Autoload::addSearchPath(dirname($standard)$namespace);
  179.                 }
  180.  
  181.                 if (PHP_CODESNIFFER_VERBOSITY === 1{
  182.                     echo "Registering sniffs in the $standardName standard... ";
  183.                     if (count($config->standards> 1 || PHP_CODESNIFFER_VERBOSITY > 2{
  184.                         echo PHP_EOL;
  185.                     }
  186.                 }
  187.  
  188.                 $sniffs array_merge($sniffs$this->processRuleset($standard));
  189.             }//end foreach
  190.         }//end if
  191.  
  192.         $sniffRestrictions = array();
  193.         foreach ($restrictions as $sniffCode{
  194.             $parts     explode('.'strtolower($sniffCode));
  195.             $sniffName $parts[0].'\sniffs\\'.$parts[1].'\\'.$parts[2].'sniff';
  196.             $sniffRestrictions[$sniffName= true;
  197.         }
  198.  
  199.         $sniffExclusions = array();
  200.         foreach ($exclusions as $sniffCode{
  201.             $parts     explode('.'strtolower($sniffCode));
  202.             $sniffName $parts[0].'\sniffs\\'.$parts[1].'\\'.$parts[2].'sniff';
  203.             $sniffExclusions[$sniffName= true;
  204.         }
  205.  
  206.         $this->registerSniffs($sniffs$sniffRestrictions$sniffExclusions);
  207.         $this->populateTokenListeners();
  208.  
  209.         $numSniffs count($this->sniffs);
  210.         if (PHP_CODESNIFFER_VERBOSITY === 1{
  211.             echo "DONE ($numSniffs sniffs registered)".PHP_EOL;
  212.         }
  213.  
  214.         if ($numSniffs === 0{
  215.             throw new RuntimeException('No sniffs were registered');
  216.         }
  217.  
  218.     }//end __construct()
  219.  
  220.  
  221.     /**
  222.      * Prints a report showing the sniffs contained in a standard.
  223.      *
  224.      * @return void 
  225.      */
  226.     public function explain()
  227.     {
  228.         $sniffs array_keys($this->sniffCodes);
  229.         sort($sniffs);
  230.  
  231.         ob_start();
  232.  
  233.         $lastStandard = null;
  234.         $lastCount    '';
  235.         $sniffCount   count($sniffs);
  236.  
  237.         // Add a dummy entry to the end so we loop
  238.         // one last time and clear the output buffer.
  239.         $sniffs['';
  240.  
  241.         echo PHP_EOL."The $this->name standard contains $sniffCount sniffs".PHP_EOL;
  242.  
  243.         ob_start();
  244.  
  245.         foreach ($sniffs as $i => $sniff{
  246.             if ($i === $sniffCount{
  247.                 $currentStandard = null;
  248.             else {
  249.                 $currentStandard substr($sniff0strpos($sniff'.'));
  250.                 if ($lastStandard === null{
  251.                     $lastStandard $currentStandard;
  252.                 }
  253.             }
  254.  
  255.             if ($currentStandard !== $lastStandard{
  256.                 $sniffList ob_get_contents();
  257.                 ob_end_clean();
  258.  
  259.                 echo PHP_EOL.$lastStandard.' ('.$lastCount.' sniff';
  260.                 if ($lastCount > 1{
  261.                     echo 's';
  262.                 }
  263.  
  264.                 echo ')'.PHP_EOL;
  265.                 echo str_repeat('-'(strlen($lastStandard.$lastCount+ 10));
  266.                 echo PHP_EOL;
  267.                 echo $sniffList;
  268.  
  269.                 $lastStandard $currentStandard;
  270.                 $lastCount    = 0;
  271.  
  272.                 if ($currentStandard === null{
  273.                     break;
  274.                 }
  275.  
  276.                 ob_start();
  277.             }//end if
  278.  
  279.             echo '  '.$sniff.PHP_EOL;
  280.             $lastCount++;
  281.         }//end foreach
  282.  
  283.     }//end explain()
  284.  
  285.  
  286.     /**
  287.      * Processes a single ruleset and returns a list of the sniffs it represents.
  288.      *
  289.      * Rules founds within the ruleset are processed immediately, but sniff classes
  290.      * are not registered by this method.
  291.      *
  292.      * @param string $rulesetPath The path to a ruleset XML file.
  293.      * @param int    $depth       How many nested processing steps we are in. This
  294.      *                             is only used for debug output.
  295.      *
  296.      * @return string[] 
  297.      * @throws RuntimeException If the ruleset path is invalid.
  298.      */
  299.     public function processRuleset($rulesetPath$depth=0)
  300.     {
  301.         $rulesetPath = Util\Common::realpath($rulesetPath);
  302.         if (PHP_CODESNIFFER_VERBOSITY > 1{
  303.             echo str_repeat("\t"$depth);
  304.             echo 'Processing ruleset '.Util\Common::stripBasepath($rulesetPath$this->config->basepath).PHP_EOL;
  305.         }
  306.  
  307.         $ruleset simplexml_load_string(file_get_contents($rulesetPath));
  308.         if ($ruleset === false{
  309.             throw new RuntimeException("Ruleset $rulesetPath is not valid");
  310.         }
  311.  
  312.         $ownSniffs      = array();
  313.         $includedSniffs = array();
  314.         $excludedSniffs = array();
  315.  
  316.         $rulesetDir          dirname($rulesetPath);
  317.         $this->rulesetDirs[$rulesetDir;
  318.  
  319.         $sniffDir $rulesetDir.DIRECTORY_SEPARATOR.'Sniffs';
  320.         if (is_dir($sniffDir=== true{
  321.             if (PHP_CODESNIFFER_VERBOSITY > 1{
  322.                 echo str_repeat("\t"$depth);
  323.                 echo "\tAdding sniff files from ".Util\Common::stripBasepath($sniffDir$this->config->basepath).' directory'.PHP_EOL;
  324.             }
  325.  
  326.             $ownSniffs $this->expandSniffDirectory($sniffDir$depth);
  327.         }
  328.  
  329.         // Included custom autoloaders.
  330.         foreach ($ruleset->{'autoload'as $autoload{
  331.             if ($this->shouldProcessElement($autoload=== false{
  332.                 continue;
  333.             }
  334.  
  335.             $autoloadPath = (string) $autoload;
  336.             if (is_file($autoloadPath=== false{
  337.                 $autoloadPath = Util\Common::realPath(dirname($rulesetPath).DIRECTORY_SEPARATOR.$autoloadPath);
  338.             }
  339.  
  340.             if ($autoloadPath === false{
  341.                 echo 'ERROR: The specified autoload file "'.$autoload.'" does not exist'.PHP_EOL.PHP_EOL;
  342.                 exit(3);
  343.             }
  344.  
  345.             include $autoloadPath;
  346.  
  347.             if (PHP_CODESNIFFER_VERBOSITY > 1{
  348.                 echo str_repeat("\t"$depth);
  349.                 echo "\t=> included autoloader $autoloadPath".PHP_EOL;
  350.             }
  351.         }//end foreach
  352.  
  353.         // Process custom sniff config settings.
  354.         foreach ($ruleset->{'config'as $config{
  355.             if ($this->shouldProcessElement($config=== false{
  356.                 continue;
  357.             }
  358.  
  359.             Config::setConfigData((string) $config['name'](string) $config['value']true);
  360.             if (PHP_CODESNIFFER_VERBOSITY > 1{
  361.                 echo str_repeat("\t"$depth);
  362.                 echo "\t=> set config value ".(string) $config['name'].': '.(string) $config['value'].PHP_EOL;
  363.             }
  364.         }
  365.  
  366.         foreach ($ruleset->rule as $rule{
  367.             if (isset($rule['ref']=== false
  368.                 || $this->shouldProcessElement($rule=== false
  369.             {
  370.                 continue;
  371.             }
  372.  
  373.             if (PHP_CODESNIFFER_VERBOSITY > 1{
  374.                 echo str_repeat("\t"$depth);
  375.                 echo "\tProcessing rule \"".$rule['ref'].'"'.PHP_EOL;
  376.             }
  377.  
  378.             $expandedSniffs $this->expandRulesetReference($rule['ref']$rulesetDir$depth);
  379.             $newSniffs      array_diff($expandedSniffs$includedSniffs);
  380.             $includedSniffs array_merge($includedSniffs$expandedSniffs);
  381.  
  382.             $parts explode('.'$rule['ref']);
  383.             if (count($parts=== 4{
  384.                 $sniffCode $parts[0].'.'.$parts[1].'.'.$parts[2];
  385.                 if (isset($this->ruleset[$sniffCode]['severity']=== true
  386.                     && $this->ruleset[$sniffCode]['severity'=== 0
  387.                 {
  388.                     // This sniff code has already been turned off, but now
  389.                     // it is being explicitly included again, so turn it back on.
  390.                     $this->ruleset[(string) $rule['ref']]['severity'= 5;
  391.                     if (PHP_CODESNIFFER_VERBOSITY > 1{
  392.                         echo str_repeat("\t"$depth);
  393.                         echo "\t\t* disabling sniff exclusion for specific message code *".PHP_EOL;
  394.                         echo str_repeat("\t"$depth);
  395.                         echo "\t\t=> severity set to 5".PHP_EOL;
  396.                     }
  397.                 else if (empty($newSniffs=== false{
  398.                     $newSniff $newSniffs[0];
  399.                     if (in_array($newSniff$ownSniffs=== false{
  400.                         // Including a sniff that hasn't been included higher up, but
  401.                         // only including a single message from it. So turn off all messages in
  402.                         // the sniff, except this one.
  403.                         $this->ruleset[$sniffCode]['severity']            = 0;
  404.                         $this->ruleset[(string) $rule['ref']]['severity'= 5;
  405.                         if (PHP_CODESNIFFER_VERBOSITY > 1{
  406.                             echo str_repeat("\t"$depth);
  407.                             echo "\t\tExcluding sniff \"".$sniffCode.'" except for "'.$parts[3].'"'.PHP_EOL;
  408.                         }
  409.                     }
  410.                 }//end if
  411.             }//end if
  412.  
  413.             if (isset($rule->exclude=== true{
  414.                 foreach ($rule->exclude as $exclude{
  415.                     if (isset($exclude['name']=== false{
  416.                         if (PHP_CODESNIFFER_VERBOSITY > 1{
  417.                             echo str_repeat("\t"$depth);
  418.                             echo "\t\t* ignoring empty exclude rule *".PHP_EOL;
  419.                             echo "\t\t\t=> ".$exclude->asXML().PHP_EOL;
  420.                         }
  421.  
  422.                         continue;
  423.                     }
  424.  
  425.                     if ($this->shouldProcessElement($exclude=== false{
  426.                         continue;
  427.                     }
  428.  
  429.                     if (PHP_CODESNIFFER_VERBOSITY > 1{
  430.                         echo str_repeat("\t"$depth);
  431.                         echo "\t\tExcluding rule \"".$exclude['name'].'"'.PHP_EOL;
  432.                     }
  433.  
  434.                     // Check if a single code is being excluded, which is a shortcut
  435.                     // for setting the severity of the message to 0.
  436.                     $parts explode('.'$exclude['name']);
  437.                     if (count($parts=== 4{
  438.                         $this->ruleset[(string) $exclude['name']]['severity'= 0;
  439.                         if (PHP_CODESNIFFER_VERBOSITY > 1{
  440.                             echo str_repeat("\t"$depth);
  441.                             echo "\t\t=> severity set to 0".PHP_EOL;
  442.                         }
  443.                     else {
  444.                         $excludedSniffs array_merge(
  445.                             $excludedSniffs,
  446.                             $this->expandRulesetReference($exclude['name']$rulesetDir($depth + 1))
  447.                         );
  448.                     }
  449.                 }//end foreach
  450.             }//end if
  451.  
  452.             $this->processRule($rule$newSniffs$depth);
  453.         }//end foreach
  454.  
  455.         // Process custom command line arguments.
  456.         $cliArgs = array();
  457.         foreach ($ruleset->{'arg'as $arg{
  458.             if ($this->shouldProcessElement($arg=== false{
  459.                 continue;
  460.             }
  461.  
  462.             if (isset($arg['name']=== true{
  463.                 $argString '--'.(string) $arg['name'];
  464.                 if (isset($arg['value']=== true{
  465.                     $argString .= '='.(string) $arg['value'];
  466.                 }
  467.             else {
  468.                 $argString '-'.(string) $arg['value'];
  469.             }
  470.  
  471.             $cliArgs[$argString;
  472.  
  473.             if (PHP_CODESNIFFER_VERBOSITY > 1{
  474.                 echo str_repeat("\t"$depth);
  475.                 echo "\t=> set command line value $argString".PHP_EOL;
  476.             }
  477.         }//end foreach
  478.  
  479.         // Set custom php ini values as CLI args.
  480.         foreach ($ruleset->{'ini'as $arg{
  481.             if ($this->shouldProcessElement($arg=== false{
  482.                 continue;
  483.             }
  484.  
  485.             if (isset($arg['name']=== false{
  486.                 continue;
  487.             }
  488.  
  489.             $name      = (string) $arg['name'];
  490.             $argString $name;
  491.             if (isset($arg['value']=== true{
  492.                 $value      = (string) $arg['value'];
  493.                 $argString .= "=$value";
  494.             else {
  495.                 $value 'true';
  496.             }
  497.  
  498.             $cliArgs['-d';
  499.             $cliArgs[$argString;
  500.  
  501.             if (PHP_CODESNIFFER_VERBOSITY > 1{
  502.                 echo str_repeat("\t"$depth);
  503.                 echo "\t=> set PHP ini value $name to $value".PHP_EOL;
  504.             }
  505.         }//end foreach
  506.  
  507.         if (empty($this->config->files=== true{
  508.             // Process hard-coded file paths.
  509.             foreach ($ruleset->{'file'as $file{
  510.                 $file      = (string) $file;
  511.                 $cliArgs[$file;
  512.                 if (PHP_CODESNIFFER_VERBOSITY > 1{
  513.                     echo str_repeat("\t"$depth);
  514.                     echo "\t=> added \"$file\" to the file list".PHP_EOL;
  515.                 }
  516.             }
  517.         }
  518.  
  519.         if (empty($cliArgs=== false{
  520.             // Change the directory so all relative paths are worked
  521.             // out based on the location of the ruleset instead of
  522.             // the location of the user.
  523.             $inPhar = Util\Common::isPharFile($rulesetDir);
  524.             if ($inPhar === false{
  525.                 $currentDir getcwd();
  526.                 chdir($rulesetDir);
  527.             }
  528.  
  529.             $this->config->setCommandLineValues($cliArgs);
  530.  
  531.             if ($inPhar === false{
  532.                 chdir($currentDir);
  533.             }
  534.         }
  535.  
  536.         // Process custom ignore pattern rules.
  537.         foreach ($ruleset->{'exclude-pattern'as $pattern{
  538.             if ($this->shouldProcessElement($pattern=== false{
  539.                 continue;
  540.             }
  541.  
  542.             if (isset($pattern['type']=== false{
  543.                 $pattern['type''absolute';
  544.             }
  545.  
  546.             $this->ignorePatterns[(string) $pattern= (string) $pattern['type'];
  547.             if (PHP_CODESNIFFER_VERBOSITY > 1{
  548.                 echo str_repeat("\t"$depth);
  549.                 echo "\t=> added global ".(string) $pattern['type'].' ignore pattern: '.(string) $pattern.PHP_EOL;
  550.             }
  551.         }
  552.  
  553.         $includedSniffs array_unique(array_merge($ownSniffs$includedSniffs));
  554.         $excludedSniffs array_unique($excludedSniffs);
  555.  
  556.         if (PHP_CODESNIFFER_VERBOSITY > 1{
  557.             $included count($includedSniffs);
  558.             $excluded count($excludedSniffs);
  559.             echo str_repeat("\t"$depth);
  560.             echo "=> Ruleset processing complete; included $included sniffs and excluded $excluded".PHP_EOL;
  561.         }
  562.  
  563.         // Merge our own sniff list with our externally included
  564.         // sniff list, but filter out any excluded sniffs.
  565.         $files = array();
  566.         foreach ($includedSniffs as $sniff{
  567.             if (in_array($sniff$excludedSniffs=== true{
  568.                 continue;
  569.             else {
  570.                 $files[= Util\Common::realpath($sniff);
  571.             }
  572.         }
  573.  
  574.         return $files;
  575.  
  576.     }//end processRuleset()
  577.  
  578.  
  579.     /**
  580.      * Expands a directory into a list of sniff files within.
  581.      *
  582.      * @param string $directory The path to a directory.
  583.      * @param int    $depth     How many nested processing steps we are in. This
  584.      *                           is only used for debug output.
  585.      *
  586.      * @return array 
  587.      */
  588.     private function expandSniffDirectory($directory$depth=0)
  589.     {
  590.         $sniffs = array();
  591.  
  592.         $rdi = new \RecursiveDirectoryIterator($directory\RecursiveDirectoryIterator::FOLLOW_SYMLINKS);
  593.         $di  = new \RecursiveIteratorIterator($rdi0\RecursiveIteratorIterator::CATCH_GET_CHILD);
  594.  
  595.         $dirLen strlen($directory);
  596.  
  597.         foreach ($di as $file{
  598.             $filename $file->getFilename();
  599.  
  600.             // Skip hidden files.
  601.             if (substr($filename01=== '.'{
  602.                 continue;
  603.             }
  604.  
  605.             // We are only interested in PHP and sniff files.
  606.             $fileParts explode('.'$filename);
  607.             if (array_pop($fileParts!== 'php'{
  608.                 continue;
  609.             }
  610.  
  611.             $basename basename($filename'.php');
  612.             if (substr($basename-5!== 'Sniff'{
  613.                 continue;
  614.             }
  615.  
  616.             $path $file->getPathname();
  617.  
  618.             // Skip files in hidden directories within the Sniffs directory of this
  619.             // standard. We use the offset with strpos() to allow hidden directories
  620.             // before, valid example:
  621.             // /home/foo/.composer/vendor/squiz/custom_tool/MyStandard/Sniffs/...
  622.             if (strpos($pathDIRECTORY_SEPARATOR.'.'$dirLen!== false{
  623.                 continue;
  624.             }
  625.  
  626.             if (PHP_CODESNIFFER_VERBOSITY > 1{
  627.                 echo str_repeat("\t"$depth);
  628.                 echo "\t\t=> ".Util\Common::stripBasepath($path$this->config->basepath).PHP_EOL;
  629.             }
  630.  
  631.             $sniffs[$path;
  632.         }//end foreach
  633.  
  634.         return $sniffs;
  635.  
  636.     }//end expandSniffDirectory()
  637.  
  638.  
  639.     /**
  640.      * Expands a ruleset reference into a list of sniff files.
  641.      *
  642.      * @param string $ref        The reference from the ruleset XML file.
  643.      * @param string $rulesetDir The directory of the ruleset XML file, used to
  644.      *                            evaluate relative paths.
  645.      * @param int    $depth      How many nested processing steps we are in. This
  646.      *                            is only used for debug output.
  647.      *
  648.      * @return array 
  649.      * @throws RuntimeException If the reference is invalid.
  650.      */
  651.     private function expandRulesetReference($ref$rulesetDir$depth=0)
  652.     {
  653.         // Ignore internal sniffs codes as they are used to only
  654.         // hide and change internal messages.
  655.         if (substr($ref09=== 'Internal.'{
  656.             if (PHP_CODESNIFFER_VERBOSITY > 1{
  657.                 echo str_repeat("\t"$depth);
  658.                 echo "\t\t* ignoring internal sniff code *".PHP_EOL;
  659.             }
  660.  
  661.             return array();
  662.         }
  663.  
  664.         // As sniffs can't begin with a full stop, assume references in
  665.         // this format are relative paths and attempt to convert them
  666.         // to absolute paths. If this fails, let the reference run through
  667.         // the normal checks and have it fail as normal.
  668.         if (substr($ref01=== '.'{
  669.             $realpath = Util\Common::realpath($rulesetDir.'/'.$ref);
  670.             if ($realpath !== false{
  671.                 $ref $realpath;
  672.                 if (PHP_CODESNIFFER_VERBOSITY > 1{
  673.                     echo str_repeat("\t"$depth);
  674.                     echo "\t\t=> ".Util\Common::stripBasepath($ref$this->config->basepath).PHP_EOL;
  675.                 }
  676.             }
  677.         }
  678.  
  679.         // As sniffs can't begin with a tilde, assume references in
  680.         // this format are relative to the user's home directory.
  681.         if (substr($ref02=== '~/'{
  682.             $realpath = Util\Common::realpath($ref);
  683.             if ($realpath !== false{
  684.                 $ref $realpath;
  685.                 if (PHP_CODESNIFFER_VERBOSITY > 1{
  686.                     echo str_repeat("\t"$depth);
  687.                     echo "\t\t=> ".Util\Common::stripBasepath($ref$this->config->basepath).PHP_EOL;
  688.                 }
  689.             }
  690.         }
  691.  
  692.         if (is_file($ref=== true{
  693.             if (substr($ref-9=== 'Sniff.php'{
  694.                 // A single external sniff.
  695.                 $this->rulesetDirs[dirname(dirname(dirname($ref)));
  696.                 return array($ref);
  697.             }
  698.         else {
  699.             // See if this is a whole standard being referenced.
  700.             $path = Util\Standards::getInstalledStandardPath($ref);
  701.             if (Util\Common::isPharFile($path=== true && strpos($path'ruleset.xml'=== false{
  702.                 // If the ruleset exists inside the phar file, use it.
  703.                 if (file_exists($path.DIRECTORY_SEPARATOR.'ruleset.xml'=== true{
  704.                     $path $path.DIRECTORY_SEPARATOR.'ruleset.xml';
  705.                 else {
  706.                     $path = null;
  707.                 }
  708.             }
  709.  
  710.             if ($path !== null{
  711.                 $ref $path;
  712.                 if (PHP_CODESNIFFER_VERBOSITY > 1{
  713.                     echo str_repeat("\t"$depth);
  714.                     echo "\t\t=> ".Util\Common::stripBasepath($ref$this->config->basepath).PHP_EOL;
  715.                 }
  716.             else if (is_dir($ref=== false{
  717.                 // Work out the sniff path.
  718.                 $sepPos strpos($refDIRECTORY_SEPARATOR);
  719.                 if ($sepPos !== false{
  720.                     $stdName substr($ref0$sepPos);
  721.                     $path    substr($ref$sepPos);
  722.                 else {
  723.                     $parts   explode('.'$ref);
  724.                     $stdName $parts[0];
  725.                     if (count($parts=== 1{
  726.                         // A whole standard?
  727.                         $path '';
  728.                     else if (count($parts=== 2{
  729.                         // A directory of sniffs?
  730.                         $path = DIRECTORY_SEPARATOR.'Sniffs'.DIRECTORY_SEPARATOR.$parts[1];
  731.                     else {
  732.                         // A single sniff?
  733.                         $path = DIRECTORY_SEPARATOR.'Sniffs'.DIRECTORY_SEPARATOR.$parts[1].DIRECTORY_SEPARATOR.$parts[2].'Sniff.php';
  734.                     }
  735.                 }
  736.  
  737.                 $newRef  = false;
  738.                 $stdPath = Util\Standards::getInstalledStandardPath($stdName);
  739.                 if ($stdPath !== null && $path !== ''{
  740.                     if (Util\Common::isPharFile($stdPath=== true
  741.                         && strpos($stdPath'ruleset.xml'=== false
  742.                     {
  743.                         // Phar files can only return the directory,
  744.                         // since ruleset can be omitted if building one standard.
  745.                         $newRef = Util\Common::realpath($stdPath.$path);
  746.                     else {
  747.                         $newRef = Util\Common::realpath(dirname($stdPath).$path);
  748.                     }
  749.                 }
  750.  
  751.                 if ($newRef === false{
  752.                     // The sniff is not locally installed, so check if it is being
  753.                     // referenced as a remote sniff outside the install. We do this
  754.                     // by looking through all directories where we have found ruleset
  755.                     // files before, looking for ones for this particular standard,
  756.                     // and seeing if it is in there.
  757.                     foreach ($this->rulesetDirs as $dir{
  758.                         if (strtolower(basename($dir)) !== strtolower($stdName)) {
  759.                             continue;
  760.                         }
  761.  
  762.                         $newRef = Util\Common::realpath($dir.$path);
  763.  
  764.                         if ($newRef !== false{
  765.                             $ref $newRef;
  766.                         }
  767.                     }
  768.                 else {
  769.                     $ref $newRef;
  770.                 }
  771.  
  772.                 if (PHP_CODESNIFFER_VERBOSITY > 1{
  773.                     echo str_repeat("\t"$depth);
  774.                     echo "\t\t=> ".Util\Common::stripBasepath($ref$this->config->basepath).PHP_EOL;
  775.                 }
  776.             }//end if
  777.         }//end if
  778.  
  779.         if (is_dir($ref=== true{
  780.             if (is_file($ref.DIRECTORY_SEPARATOR.'ruleset.xml'=== true{
  781.                 // We are referencing an external coding standard.
  782.                 if (PHP_CODESNIFFER_VERBOSITY > 1{
  783.                     echo str_repeat("\t"$depth);
  784.                     echo "\t\t* rule is referencing a standard using directory name; processing *".PHP_EOL;
  785.                 }
  786.  
  787.                 return $this->processRuleset($ref.DIRECTORY_SEPARATOR.'ruleset.xml'($depth + 2));
  788.             else {
  789.                 // We are referencing a whole directory of sniffs.
  790.                 if (PHP_CODESNIFFER_VERBOSITY > 1{
  791.                     echo str_repeat("\t"$depth);
  792.                     echo "\t\t* rule is referencing a directory of sniffs *".PHP_EOL;
  793.                     echo str_repeat("\t"$depth);
  794.                     echo "\t\tAdding sniff files from directory".PHP_EOL;
  795.                 }
  796.  
  797.                 return $this->expandSniffDirectory($ref($depth + 1));
  798.             }
  799.         else {
  800.             if (is_file($ref=== false{
  801.                 $error = "Referenced sniff \"$ref\" does not exist";
  802.                 throw new RuntimeException($error);
  803.             }
  804.  
  805.             if (substr($ref-9=== 'Sniff.php'{
  806.                 // A single sniff.
  807.                 return array($ref);
  808.             else {
  809.                 // Assume an external ruleset.xml file.
  810.                 if (PHP_CODESNIFFER_VERBOSITY > 1{
  811.                     echo str_repeat("\t"$depth);
  812.                     echo "\t\t* rule is referencing a standard using ruleset path; processing *".PHP_EOL;
  813.                 }
  814.  
  815.                 return $this->processRuleset($ref($depth + 2));
  816.             }
  817.         }//end if
  818.  
  819.     }//end expandRulesetReference()
  820.  
  821.  
  822.     /**
  823.      * Processes a rule from a ruleset XML file, overriding built-in defaults.
  824.      *
  825.      * @param SimpleXMLElement $rule      The rule object from a ruleset XML file.
  826.      * @param string[]         $newSniffs An array of sniffs that got included by this rule.
  827.      * @param int              $depth     How many nested processing steps we are in.
  828.      *                                     This is only used for debug output.
  829.      *
  830.      * @return void 
  831.      * @throws RuntimeException If rule settings are invalid.
  832.      */
  833.     private function processRule($rule$newSniffs$depth=0)
  834.     {
  835.         $ref  = (string) $rule['ref'];
  836.         $todo = array($ref);
  837.  
  838.         $parts explode('.'$ref);
  839.         if (count($parts<= 2{
  840.             // We are processing a standard or a category of sniffs.
  841.             foreach ($newSniffs as $sniffFile{
  842.                 $parts         explode(DIRECTORY_SEPARATOR$sniffFile);
  843.                 $sniffName     array_pop($parts);
  844.                 $sniffCategory array_pop($parts);
  845.                 array_pop($parts);
  846.                 $sniffStandard array_pop($parts);
  847.                 $todo[]        $sniffStandard.'.'.$sniffCategory.'.'.substr($sniffName0-9);
  848.             }
  849.         }
  850.  
  851.         foreach ($todo as $code{
  852.             // Custom severity.
  853.             if (isset($rule->severity=== true
  854.                 && $this->shouldProcessElement($rule->severity=== true
  855.             {
  856.                 if (isset($this->ruleset[$code]=== false{
  857.                     $this->ruleset[$code= array();
  858.                 }
  859.  
  860.                 $this->ruleset[$code]['severity'= (int) $rule->severity;
  861.                 if (PHP_CODESNIFFER_VERBOSITY > 1{
  862.                     echo str_repeat("\t"$depth);
  863.                     echo "\t\t=> severity set to ".(int) $rule->severity;
  864.                     if ($code !== $ref{
  865.                         echo " for $code";
  866.                     }
  867.  
  868.                     echo PHP_EOL;
  869.                 }
  870.             }
  871.  
  872.             // Custom message type.
  873.             if (isset($rule->type=== true
  874.                 && $this->shouldProcessElement($rule->type=== true
  875.             {
  876.                 if (isset($this->ruleset[$code]=== false{
  877.                     $this->ruleset[$code= array();
  878.                 }
  879.  
  880.                 $type strtolower((string) $rule->type);
  881.                 if ($type !== 'error' && $type !== 'warning'{
  882.                     throw new RuntimeException("Message type \"$type\" is invalid; must be \"error\" or \"warning\"");
  883.                 }
  884.  
  885.                 $this->ruleset[$code]['type'$type;
  886.                 if (PHP_CODESNIFFER_VERBOSITY > 1{
  887.                     echo str_repeat("\t"$depth);
  888.                     echo "\t\t=> message type set to ".(string) $rule->type;
  889.                     if ($code !== $ref{
  890.                         echo " for $code";
  891.                     }
  892.  
  893.                     echo PHP_EOL;
  894.                 }
  895.             }//end if
  896.  
  897.             // Custom message.
  898.             if (isset($rule->message=== true
  899.                 && $this->shouldProcessElement($rule->message=== true
  900.             {
  901.                 if (isset($this->ruleset[$code]=== false{
  902.                     $this->ruleset[$code= array();
  903.                 }
  904.  
  905.                 $this->ruleset[$code]['message'= (string) $rule->message;
  906.                 if (PHP_CODESNIFFER_VERBOSITY > 1{
  907.                     echo str_repeat("\t"$depth);
  908.                     echo "\t\t=> message set to ".(string) $rule->message;
  909.                     if ($code !== $ref{
  910.                         echo " for $code";
  911.                     }
  912.  
  913.                     echo PHP_EOL;
  914.                 }
  915.             }
  916.  
  917.             // Custom properties.
  918.             if (isset($rule->properties=== true
  919.                 && $this->shouldProcessElement($rule->properties=== true
  920.             {
  921.                 foreach ($rule->properties->property as $prop{
  922.                     if ($this->shouldProcessElement($prop=== false{
  923.                         continue;
  924.                     }
  925.  
  926.                     if (isset($this->ruleset[$code]=== false{
  927.                         $this->ruleset[$code= array(
  928.                                                  'properties' => array(),
  929.                                                 );
  930.                     else if (isset($this->ruleset[$code]['properties']=== false{
  931.                         $this->ruleset[$code]['properties'= array();
  932.                     }
  933.  
  934.                     $name = (string) $prop['name'];
  935.                     if (isset($prop['type']=== true
  936.                         && (string) $prop['type'=== 'array'
  937.                     {
  938.                         $value  = (string) $prop['value'];
  939.                         $values = array();
  940.                         foreach (explode(','$valueas $val{
  941.                             $v '';
  942.  
  943.                             list($k,$vexplode('=>'$val.'=>');
  944.                             if ($v !== ''{
  945.                                 $values[$k$v;
  946.                             else {
  947.                                 $values[$k;
  948.                             }
  949.                         }
  950.  
  951.                         $this->ruleset[$code]['properties'][$name$values;
  952.                         if (PHP_CODESNIFFER_VERBOSITY > 1{
  953.                             echo str_repeat("\t"$depth);
  954.                             echo "\t\t=> array property \"$name\" set to \"$value\"";
  955.                             if ($code !== $ref{
  956.                                 echo " for $code";
  957.                             }
  958.  
  959.                             echo PHP_EOL;
  960.                         }
  961.                     else {
  962.                         $this->ruleset[$code]['properties'][$name= (string) $prop['value'];
  963.                         if (PHP_CODESNIFFER_VERBOSITY > 1{
  964.                             echo str_repeat("\t"$depth);
  965.                             echo "\t\t=> property \"$name\" set to \"".(string) $prop['value'].'"';
  966.                             if ($code !== $ref{
  967.                                 echo " for $code";
  968.                             }
  969.  
  970.                             echo PHP_EOL;
  971.                         }
  972.                     }//end if
  973.                 }//end foreach
  974.             }//end if
  975.  
  976.             // Ignore patterns.
  977.             foreach ($rule->{'exclude-pattern'as $pattern{
  978.                 if ($this->shouldProcessElement($pattern=== false{
  979.                     continue;
  980.                 }
  981.  
  982.                 if (isset($this->ignorePatterns[$code]=== false{
  983.                     $this->ignorePatterns[$code= array();
  984.                 }
  985.  
  986.                 if (isset($pattern['type']=== false{
  987.                     $pattern['type''absolute';
  988.                 }
  989.  
  990.                 $this->ignorePatterns[$code][(string) $pattern= (string) $pattern['type'];
  991.                 if (PHP_CODESNIFFER_VERBOSITY > 1{
  992.                     echo str_repeat("\t"$depth);
  993.                     echo "\t\t=> added rule-specific ".(string) $pattern['type'].' ignore pattern';
  994.                     if ($code !== $ref{
  995.                         echo " for $code";
  996.                     }
  997.  
  998.                     echo ': '.(string) $pattern.PHP_EOL;
  999.                 }
  1000.             }//end foreach
  1001.  
  1002.             // Include patterns.
  1003.             foreach ($rule->{'include-pattern'as $pattern{
  1004.                 if ($this->shouldProcessElement($pattern=== false{
  1005.                     continue;
  1006.                 }
  1007.  
  1008.                 if (isset($this->includePatterns[$code]=== false{
  1009.                     $this->includePatterns[$code= array();
  1010.                 }
  1011.  
  1012.                 if (isset($pattern['type']=== false{
  1013.                     $pattern['type''absolute';
  1014.                 }
  1015.  
  1016.                 $this->includePatterns[$code][(string) $pattern= (string) $pattern['type'];
  1017.                 if (PHP_CODESNIFFER_VERBOSITY > 1{
  1018.                     echo str_repeat("\t"$depth);
  1019.                     echo "\t\t=> added rule-specific ".(string) $pattern['type'].' include pattern';
  1020.                     if ($code !== $ref{
  1021.                         echo " for $code";
  1022.                     }
  1023.  
  1024.                     echo ': '.(string) $pattern.PHP_EOL;
  1025.                 }
  1026.             }//end foreach
  1027.         }//end foreach
  1028.  
  1029.     }//end processRule()
  1030.  
  1031.  
  1032.     /**
  1033.      * Determine if an element should be processed or ignored.
  1034.      *
  1035.      * @param SimpleXMLElement $element An object from a ruleset XML file.
  1036.      *
  1037.      * @return bool 
  1038.      */
  1039.     private function shouldProcessElement($element)
  1040.     {
  1041.         if (isset($element['phpcbf-only']=== false
  1042.             && isset($element['phpcs-only']=== false
  1043.         {
  1044.             // No exceptions are being made.
  1045.             return true;
  1046.         }
  1047.  
  1048.         if (PHP_CODESNIFFER_CBF === true
  1049.             && isset($element['phpcbf-only']=== true
  1050.             && (string) $element['phpcbf-only'=== 'true'
  1051.         {
  1052.             return true;
  1053.         }
  1054.  
  1055.         if (PHP_CODESNIFFER_CBF === false
  1056.             && isset($element['phpcs-only']=== true
  1057.             && (string) $element['phpcs-only'=== 'true'
  1058.         {
  1059.             return true;
  1060.         }
  1061.  
  1062.         return false;
  1063.  
  1064.     }//end shouldProcessElement()
  1065.  
  1066.  
  1067.     /**
  1068.      * Loads and stores sniffs objects used for sniffing files.
  1069.      *
  1070.      * @param array $files        Paths to the sniff files to register.
  1071.      * @param array $restrictions The sniff class names to restrict the allowed
  1072.      *                             listeners to.
  1073.      * @param array $exclusions   The sniff class names to exclude from the
  1074.      *                             listeners list.
  1075.      *
  1076.      * @return void 
  1077.      */
  1078.     public function registerSniffs($files$restrictions$exclusions)
  1079.     {
  1080.         $listeners = array();
  1081.  
  1082.         foreach ($files as $file{
  1083.             // Work out where the position of /StandardName/Sniffs/... is
  1084.             // so we can determine what the class will be called.
  1085.             $sniffPos strrpos($fileDIRECTORY_SEPARATOR.'Sniffs'.DIRECTORY_SEPARATOR);
  1086.             if ($sniffPos === false{
  1087.                 continue;
  1088.             }
  1089.  
  1090.             $slashPos strrpos(substr($file0$sniffPos)DIRECTORY_SEPARATOR);
  1091.             if ($slashPos === false{
  1092.                 continue;
  1093.             }
  1094.  
  1095.             $className   = Autoload::loadFile($file);
  1096.             $compareName = Util\Common::cleanSniffClass($className);
  1097.  
  1098.             // If they have specified a list of sniffs to restrict to, check
  1099.             // to see if this sniff is allowed.
  1100.             if (empty($restrictions=== false
  1101.                 && isset($restrictions[$compareName]=== false
  1102.             {
  1103.                 continue;
  1104.             }
  1105.  
  1106.             // If they have specified a list of sniffs to exclude, check
  1107.             // to see if this sniff is allowed.
  1108.             if (empty($exclusions=== false
  1109.                 && isset($exclusions[$compareName]=== true
  1110.             {
  1111.                 continue;
  1112.             }
  1113.  
  1114.             // Skip abstract classes.
  1115.             $reflection = new \ReflectionClass($className);
  1116.             if ($reflection->isAbstract(=== true{
  1117.                 continue;
  1118.             }
  1119.  
  1120.             $listeners[$className$className;
  1121.  
  1122.             if (PHP_CODESNIFFER_VERBOSITY > 2{
  1123.                 echo "Registered $className".PHP_EOL;
  1124.             }
  1125.         }//end foreach
  1126.  
  1127.         $this->sniffs = $listeners;
  1128.  
  1129.     }//end registerSniffs()
  1130.  
  1131.  
  1132.     /**
  1133.      * Populates the array of PHP_CodeSniffer_Sniff's for this file.
  1134.      *
  1135.      * @return void 
  1136.      * @throws RuntimeException If sniff registration fails.
  1137.      */
  1138.     public function populateTokenListeners()
  1139.     {
  1140.         // Construct a list of listeners indexed by token being listened for.
  1141.         $this->tokenListeners = array();
  1142.  
  1143.         foreach ($this->sniffs as $sniffClass => $sniffObject{
  1144.             $this->sniffs[$sniffClass= null;
  1145.             $this->sniffs[$sniffClass= new $sniffClass();
  1146.  
  1147.             $sniffCode = Util\Common::getSniffCode($sniffClass);
  1148.             $this->sniffCodes[$sniffCode$sniffClass;
  1149.  
  1150.             // Set custom properties.
  1151.             if (isset($this->ruleset[$sniffCode]['properties']=== true{
  1152.                 foreach ($this->ruleset[$sniffCode]['properties'as $name => $value{
  1153.                     $this->setSniffProperty($sniffClass$name$value);
  1154.                 }
  1155.             }
  1156.  
  1157.             $tokenizers = array();
  1158.             $vars       get_class_vars($sniffClass);
  1159.             if (isset($vars['supportedTokenizers']=== true{
  1160.                 foreach ($vars['supportedTokenizers'as $tokenizer{
  1161.                     $tokenizers[$tokenizer$tokenizer;
  1162.                 }
  1163.             else {
  1164.                 $tokenizers = array('PHP' => 'PHP');
  1165.             }
  1166.  
  1167.             $tokens $this->sniffs[$sniffClass]->register();
  1168.             if (is_array($tokens=== false{
  1169.                 $msg = "Sniff $sniffClass register() method must return an array";
  1170.                 throw new RuntimeException($msg);
  1171.             }
  1172.  
  1173.             $ignorePatterns = array();
  1174.             $patterns       $this->getIgnorePatterns($sniffCode);
  1175.             foreach ($patterns as $pattern => $type{
  1176.                 $replacements = array(
  1177.                                  '\\,' => ',',
  1178.                                  '*'   => '.*',
  1179.                                 );
  1180.  
  1181.                 $ignorePatterns[strtr($pattern$replacements);
  1182.             }
  1183.  
  1184.             $includePatterns = array();
  1185.             $patterns        $this->getIncludePatterns($sniffCode);
  1186.             foreach ($patterns as $pattern => $type{
  1187.                 $replacements = array(
  1188.                                  '\\,' => ',',
  1189.                                  '*'   => '.*',
  1190.                                 );
  1191.  
  1192.                 $includePatterns[strtr($pattern$replacements);
  1193.             }
  1194.  
  1195.             foreach ($tokens as $token{
  1196.                 if (isset($this->tokenListeners[$token]=== false{
  1197.                     $this->tokenListeners[$token= array();
  1198.                 }
  1199.  
  1200.                 if (isset($this->tokenListeners[$token][$sniffClass]=== false{
  1201.                     $this->tokenListeners[$token][$sniffClass= array(
  1202.                                                                   'class'      => $sniffClass,
  1203.                                                                   'source'     => $sniffCode,
  1204.                                                                   'tokenizers' => $tokenizers,
  1205.                                                                   'ignore'     => $ignorePatterns,
  1206.                                                                   'include'    => $includePatterns,
  1207.                                                                  );
  1208.                 }
  1209.             }
  1210.         }//end foreach
  1211.  
  1212.     }//end populateTokenListeners()
  1213.  
  1214.  
  1215.     /**
  1216.      * Set a single property for a sniff.
  1217.      *
  1218.      * @param string $sniffClass The class name of the sniff.
  1219.      * @param string $name       The name of the property to change.
  1220.      * @param string $value      The new value of the property.
  1221.      *
  1222.      * @return void 
  1223.      */
  1224.     public function setSniffProperty($sniffClass$name$value)
  1225.     {
  1226.         // Setting a property for a sniff we are not using.
  1227.         if (isset($this->sniffs[$sniffClass]=== false{
  1228.             return;
  1229.         }
  1230.  
  1231.         $name trim($name);
  1232.         if (is_string($value=== true{
  1233.             $value trim($value);
  1234.         }
  1235.  
  1236.         // Special case for booleans.
  1237.         if ($value === 'true'{
  1238.             $value = true;
  1239.         else if ($value === 'false'{
  1240.             $value = false;
  1241.         }
  1242.  
  1243.         $this->sniffs[$sniffClass]->$name $value;
  1244.  
  1245.     }//end setSniffProperty()
  1246.  
  1247.  
  1248.     /**
  1249.      * Gets the array of ignore patterns.
  1250.      *
  1251.      * Optionally takes a listener to get ignore patterns specified
  1252.      * for that sniff only.
  1253.      *
  1254.      * @param string $listener The listener to get patterns for. If NULL, all
  1255.      *                          patterns are returned.
  1256.      *
  1257.      * @return array 
  1258.      */
  1259.     public function getIgnorePatterns($listener=null)
  1260.     {
  1261.         if ($listener === null{
  1262.             return $this->ignorePatterns;
  1263.         }
  1264.  
  1265.         if (isset($this->ignorePatterns[$listener]=== true{
  1266.             return $this->ignorePatterns[$listener];
  1267.         }
  1268.  
  1269.         return array();
  1270.  
  1271.     }//end getIgnorePatterns()
  1272.  
  1273.  
  1274.     /**
  1275.      * Gets the array of include patterns.
  1276.      *
  1277.      * Optionally takes a listener to get include patterns specified
  1278.      * for that sniff only.
  1279.      *
  1280.      * @param string $listener The listener to get patterns for. If NULL, all
  1281.      *                          patterns are returned.
  1282.      *
  1283.      * @return array 
  1284.      */
  1285.     public function getIncludePatterns($listener=null)
  1286.     {
  1287.         if ($listener === null{
  1288.             return $this->includePatterns;
  1289.         }
  1290.  
  1291.         if (isset($this->includePatterns[$listener]=== true{
  1292.             return $this->includePatterns[$listener];
  1293.         }
  1294.  
  1295.         return array();
  1296.  
  1297.     }//end getIncludePatterns()
  1298.  
  1299.  
  1300. }//end class

Documentation generated on Mon, 11 Mar 2019 14:18:10 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.