Chris@17: Chris@17: * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) Chris@17: * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence Chris@17: */ Chris@17: Chris@17: namespace PHP_CodeSniffer\Files; Chris@17: Chris@18: use PHP_CodeSniffer\Autoload; Chris@17: use PHP_CodeSniffer\Util; Chris@17: use PHP_CodeSniffer\Ruleset; Chris@17: use PHP_CodeSniffer\Config; Chris@17: use PHP_CodeSniffer\Exceptions\DeepExitException; Chris@17: Chris@17: class FileList implements \Iterator, \Countable Chris@17: { Chris@17: Chris@17: /** Chris@17: * A list of file paths that are included in the list. Chris@17: * Chris@17: * @var array Chris@17: */ Chris@17: private $files = []; Chris@17: Chris@17: /** Chris@17: * The number of files in the list. Chris@17: * Chris@17: * @var integer Chris@17: */ Chris@17: private $numFiles = 0; Chris@17: Chris@17: /** Chris@17: * The config data for the run. Chris@17: * Chris@17: * @var \PHP_CodeSniffer\Config Chris@17: */ Chris@17: public $config = null; Chris@17: Chris@17: /** Chris@17: * The ruleset used for the run. Chris@17: * Chris@17: * @var \PHP_CodeSniffer\Ruleset Chris@17: */ Chris@17: public $ruleset = null; Chris@17: Chris@17: /** Chris@17: * An array of patterns to use for skipping files. Chris@17: * Chris@17: * @var array Chris@17: */ Chris@17: protected $ignorePatterns = []; Chris@17: Chris@17: Chris@17: /** Chris@17: * Constructs a file list and loads in an array of file paths to process. Chris@17: * Chris@17: * @param \PHP_CodeSniffer\Config $config The config data for the run. Chris@17: * @param \PHP_CodeSniffer\Ruleset $ruleset The ruleset used for the run. Chris@17: * Chris@17: * @return void Chris@17: */ Chris@17: public function __construct(Config $config, Ruleset $ruleset) Chris@17: { Chris@17: $this->ruleset = $ruleset; Chris@17: $this->config = $config; Chris@17: Chris@17: $paths = $config->files; Chris@17: foreach ($paths as $path) { Chris@17: $isPharFile = Util\Common::isPharFile($path); Chris@17: if (is_dir($path) === true || $isPharFile === true) { Chris@17: if ($isPharFile === true) { Chris@17: $path = 'phar://'.$path; Chris@17: } Chris@17: Chris@17: $filterClass = $this->getFilterClass(); Chris@17: Chris@17: $di = new \RecursiveDirectoryIterator($path, (\RecursiveDirectoryIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS)); Chris@17: $filter = new $filterClass($di, $path, $config, $ruleset); Chris@17: $iterator = new \RecursiveIteratorIterator($filter); Chris@17: Chris@17: foreach ($iterator as $file) { Chris@17: $this->files[$file->getPathname()] = null; Chris@17: $this->numFiles++; Chris@17: } Chris@17: } else { Chris@17: $this->addFile($path); Chris@17: }//end if Chris@17: }//end foreach Chris@17: Chris@17: reset($this->files); Chris@17: Chris@17: }//end __construct() Chris@17: Chris@17: Chris@17: /** Chris@17: * Add a file to the list. Chris@17: * Chris@17: * If a file object has already been created, it can be passed here. Chris@17: * If it is left NULL, it will be created when accessed. Chris@17: * Chris@17: * @param string $path The path to the file being added. Chris@17: * @param \PHP_CodeSniffer\Files\File $file The file being added. Chris@17: * Chris@17: * @return void Chris@17: */ Chris@17: public function addFile($path, $file=null) Chris@17: { Chris@17: // No filtering is done for STDIN when the filename Chris@17: // has not been specified. Chris@17: if ($path === 'STDIN') { Chris@17: $this->files[$path] = $file; Chris@17: $this->numFiles++; Chris@17: return; Chris@17: } Chris@17: Chris@17: $filterClass = $this->getFilterClass(); Chris@17: Chris@17: $di = new \RecursiveArrayIterator([$path]); Chris@17: $filter = new $filterClass($di, $path, $this->config, $this->ruleset); Chris@17: $iterator = new \RecursiveIteratorIterator($filter); Chris@17: Chris@17: foreach ($iterator as $path) { Chris@17: $this->files[$path] = $file; Chris@17: $this->numFiles++; Chris@17: } Chris@17: Chris@17: }//end addFile() Chris@17: Chris@17: Chris@17: /** Chris@17: * Get the class name of the filter being used for the run. Chris@17: * Chris@17: * @return string Chris@17: */ Chris@17: private function getFilterClass() Chris@17: { Chris@17: $filterType = $this->config->filter; Chris@17: Chris@17: if ($filterType === null) { Chris@17: $filterClass = '\PHP_CodeSniffer\Filters\Filter'; Chris@17: } else { Chris@17: if (strpos($filterType, '.') !== false) { Chris@17: // This is a path to a custom filter class. Chris@17: $filename = realpath($filterType); Chris@17: if ($filename === false) { Chris@17: $error = "ERROR: Custom filter \"$filterType\" not found".PHP_EOL; Chris@17: throw new DeepExitException($error, 3); Chris@17: } Chris@17: Chris@18: $filterClass = Autoload::loadFile($filename); Chris@17: } else { Chris@17: $filterClass = '\PHP_CodeSniffer\Filters\\'.$filterType; Chris@17: } Chris@17: } Chris@17: Chris@17: return $filterClass; Chris@17: Chris@17: }//end getFilterClass() Chris@17: Chris@17: Chris@17: /** Chris@17: * Rewind the iterator to the first file. Chris@17: * Chris@17: * @return void Chris@17: */ Chris@17: public function rewind() Chris@17: { Chris@17: reset($this->files); Chris@17: Chris@17: }//end rewind() Chris@17: Chris@17: Chris@17: /** Chris@17: * Get the file that is currently being processed. Chris@17: * Chris@17: * @return \PHP_CodeSniffer\Files\File Chris@17: */ Chris@17: public function current() Chris@17: { Chris@17: $path = key($this->files); Chris@17: if ($this->files[$path] === null) { Chris@17: $this->files[$path] = new LocalFile($path, $this->ruleset, $this->config); Chris@17: } Chris@17: Chris@17: return $this->files[$path]; Chris@17: Chris@17: }//end current() Chris@17: Chris@17: Chris@17: /** Chris@17: * Return the file path of the current file being processed. Chris@17: * Chris@17: * @return void Chris@17: */ Chris@17: public function key() Chris@17: { Chris@17: return key($this->files); Chris@17: Chris@17: }//end key() Chris@17: Chris@17: Chris@17: /** Chris@17: * Move forward to the next file. Chris@17: * Chris@17: * @return void Chris@17: */ Chris@17: public function next() Chris@17: { Chris@17: next($this->files); Chris@17: Chris@17: }//end next() Chris@17: Chris@17: Chris@17: /** Chris@17: * Checks if current position is valid. Chris@17: * Chris@17: * @return boolean Chris@17: */ Chris@17: public function valid() Chris@17: { Chris@17: if (current($this->files) === false) { Chris@17: return false; Chris@17: } Chris@17: Chris@17: return true; Chris@17: Chris@17: }//end valid() Chris@17: Chris@17: Chris@17: /** Chris@17: * Return the number of files in the list. Chris@17: * Chris@17: * @return integer Chris@17: */ Chris@17: public function count() Chris@17: { Chris@17: return $this->numFiles; Chris@17: Chris@17: }//end count() Chris@17: Chris@17: Chris@17: }//end class