PageRenderTime 27ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/php/PHP_CodeSniffer/src/Filters/Filter.php

http://github.com/jonswar/perl-code-tidyall
PHP | 280 lines | 133 code | 46 blank | 101 comment | 22 complexity | aa4f8c9fdc034a88b4f7eff8941d2552 MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, 0BSD, MIT
  1. <?php
  2. /**
  3. * A base filter class for filtering out files and folders during a run.
  4. *
  5. * @author Greg Sherwood <gsherwood@squiz.net>
  6. * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
  7. * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
  8. */
  9. namespace PHP_CodeSniffer\Filters;
  10. use PHP_CodeSniffer\Util;
  11. use PHP_CodeSniffer\Ruleset;
  12. use PHP_CodeSniffer\Config;
  13. class Filter extends \RecursiveFilterIterator
  14. {
  15. /**
  16. * The top-level path we are filtering.
  17. *
  18. * @var string
  19. */
  20. protected $basedir = null;
  21. /**
  22. * The config data for the run.
  23. *
  24. * @var \PHP_CodeSniffer\Config
  25. */
  26. protected $config = null;
  27. /**
  28. * The ruleset used for the run.
  29. *
  30. * @var \PHP_CodeSniffer\Ruleset
  31. */
  32. protected $ruleset = null;
  33. /**
  34. * A list of ignore patterns that apply to directories only.
  35. *
  36. * @var array
  37. */
  38. protected $ignoreDirPatterns = null;
  39. /**
  40. * A list of ignore patterns that apply to files only.
  41. *
  42. * @var array
  43. */
  44. protected $ignoreFilePatterns = null;
  45. /**
  46. * A list of file paths we've already accepted.
  47. *
  48. * Used to ensure we aren't following circular symlinks.
  49. *
  50. * @var array
  51. */
  52. protected $acceptedPaths = [];
  53. /**
  54. * Constructs a filter.
  55. *
  56. * @param \RecursiveIterator $iterator The iterator we are using to get file paths.
  57. * @param string $basedir The top-level path we are filtering.
  58. * @param \PHP_CodeSniffer\Config $config The config data for the run.
  59. * @param \PHP_CodeSniffer\Ruleset $ruleset The ruleset used for the run.
  60. *
  61. * @return void
  62. */
  63. public function __construct($iterator, $basedir, Config $config, Ruleset $ruleset)
  64. {
  65. parent::__construct($iterator);
  66. $this->basedir = $basedir;
  67. $this->config = $config;
  68. $this->ruleset = $ruleset;
  69. }//end __construct()
  70. /**
  71. * Check whether the current element of the iterator is acceptable.
  72. *
  73. * Files are checked for allowed extensions and ignore patterns.
  74. * Directories are checked for ignore patterns only.
  75. *
  76. * @return bool
  77. */
  78. public function accept()
  79. {
  80. $filePath = $this->current();
  81. $realPath = Util\Common::realpath($filePath);
  82. if ($realPath !== false) {
  83. // It's a real path somewhere, so record it
  84. // to check for circular symlinks.
  85. if (isset($this->acceptedPaths[$realPath]) === true) {
  86. // We've been here before.
  87. return false;
  88. }
  89. }
  90. $filePath = $this->current();
  91. if (is_dir($filePath) === true) {
  92. if ($this->config->local === true) {
  93. return false;
  94. }
  95. } else if ($this->shouldProcessFile($filePath) === false) {
  96. return false;
  97. }
  98. if ($this->shouldIgnorePath($filePath) === true) {
  99. return false;
  100. }
  101. $this->acceptedPaths[$realPath] = true;
  102. return true;
  103. }//end accept()
  104. /**
  105. * Returns an iterator for the current entry.
  106. *
  107. * Ensures that the ignore patterns are preserved so they don't have
  108. * to be generated each time.
  109. *
  110. * @return \RecursiveIterator
  111. */
  112. public function getChildren()
  113. {
  114. $children = new static(
  115. new \RecursiveDirectoryIterator($this->current(), (\RecursiveDirectoryIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS)),
  116. $this->basedir,
  117. $this->config,
  118. $this->ruleset
  119. );
  120. // Set the ignore patterns so we don't have to generate them again.
  121. $children->ignoreDirPatterns = $this->ignoreDirPatterns;
  122. $children->ignoreFilePatterns = $this->ignoreFilePatterns;
  123. $children->acceptedPaths = $this->acceptedPaths;
  124. return $children;
  125. }//end getChildren()
  126. /**
  127. * Checks filtering rules to see if a file should be checked.
  128. *
  129. * Checks both file extension filters and path ignore filters.
  130. *
  131. * @param string $path The path to the file being checked.
  132. *
  133. * @return bool
  134. */
  135. protected function shouldProcessFile($path)
  136. {
  137. // Check that the file's extension is one we are checking.
  138. // We are strict about checking the extension and we don't
  139. // let files through with no extension or that start with a dot.
  140. $fileName = basename($path);
  141. $fileParts = explode('.', $fileName);
  142. if ($fileParts[0] === $fileName || $fileParts[0] === '') {
  143. return false;
  144. }
  145. // Checking multi-part file extensions, so need to create a
  146. // complete extension list and make sure one is allowed.
  147. $extensions = [];
  148. array_shift($fileParts);
  149. foreach ($fileParts as $part) {
  150. $extensions[implode('.', $fileParts)] = 1;
  151. array_shift($fileParts);
  152. }
  153. $matches = array_intersect_key($extensions, $this->config->extensions);
  154. if (empty($matches) === true) {
  155. return false;
  156. }
  157. return true;
  158. }//end shouldProcessFile()
  159. /**
  160. * Checks filtering rules to see if a path should be ignored.
  161. *
  162. * @param string $path The path to the file or directory being checked.
  163. *
  164. * @return bool
  165. */
  166. protected function shouldIgnorePath($path)
  167. {
  168. if ($this->ignoreFilePatterns === null) {
  169. $this->ignoreDirPatterns = [];
  170. $this->ignoreFilePatterns = [];
  171. $ignorePatterns = $this->config->ignored;
  172. $rulesetIgnorePatterns = $this->ruleset->getIgnorePatterns();
  173. foreach ($rulesetIgnorePatterns as $pattern => $type) {
  174. // Ignore standard/sniff specific exclude rules.
  175. if (is_array($type) === true) {
  176. continue;
  177. }
  178. $ignorePatterns[$pattern] = $type;
  179. }
  180. foreach ($ignorePatterns as $pattern => $type) {
  181. // If the ignore pattern ends with /* then it is ignoring an entire directory.
  182. if (substr($pattern, -2) === '/*') {
  183. // Need to check this pattern for dirs as well as individual file paths.
  184. $this->ignoreFilePatterns[$pattern] = $type;
  185. $pattern = substr($pattern, 0, -2);
  186. $this->ignoreDirPatterns[$pattern] = $type;
  187. } else {
  188. // This is a file-specific pattern, so only need to check this
  189. // for individual file paths.
  190. $this->ignoreFilePatterns[$pattern] = $type;
  191. }
  192. }
  193. }//end if
  194. $relativePath = $path;
  195. if (strpos($path, $this->basedir) === 0) {
  196. // The +1 cuts off the directory separator as well.
  197. $relativePath = substr($path, (strlen($this->basedir) + 1));
  198. }
  199. if (is_dir($path) === true) {
  200. $ignorePatterns = $this->ignoreDirPatterns;
  201. } else {
  202. $ignorePatterns = $this->ignoreFilePatterns;
  203. }
  204. foreach ($ignorePatterns as $pattern => $type) {
  205. // Maintains backwards compatibility in case the ignore pattern does
  206. // not have a relative/absolute value.
  207. if (is_int($pattern) === true) {
  208. $pattern = $type;
  209. $type = 'absolute';
  210. }
  211. $replacements = [
  212. '\\,' => ',',
  213. '*' => '.*',
  214. ];
  215. // We assume a / directory separator, as do the exclude rules
  216. // most developers write, so we need a special case for any system
  217. // that is different.
  218. if (DIRECTORY_SEPARATOR === '\\') {
  219. $replacements['/'] = '\\\\';
  220. }
  221. $pattern = strtr($pattern, $replacements);
  222. if ($type === 'relative') {
  223. $testPath = $relativePath;
  224. } else {
  225. $testPath = $path;
  226. }
  227. $pattern = '`'.$pattern.'`i';
  228. if (preg_match($pattern, $testPath) === 1) {
  229. return true;
  230. }
  231. }//end foreach
  232. return false;
  233. }//end shouldIgnorePath()
  234. }//end class