annotate vendor/symfony/finder/Finder.php @ 8:50b0d041100e

Further files for download
author Chris Cannam
date Mon, 05 Feb 2018 10:56:40 +0000
parents 4c8ae668cc8c
children 7a779792577d
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 /*
Chris@0 4 * This file is part of the Symfony package.
Chris@0 5 *
Chris@0 6 * (c) Fabien Potencier <fabien@symfony.com>
Chris@0 7 *
Chris@0 8 * For the full copyright and license information, please view the LICENSE
Chris@0 9 * file that was distributed with this source code.
Chris@0 10 */
Chris@0 11
Chris@0 12 namespace Symfony\Component\Finder;
Chris@0 13
Chris@0 14 use Symfony\Component\Finder\Comparator\DateComparator;
Chris@0 15 use Symfony\Component\Finder\Comparator\NumberComparator;
Chris@0 16 use Symfony\Component\Finder\Iterator\CustomFilterIterator;
Chris@0 17 use Symfony\Component\Finder\Iterator\DateRangeFilterIterator;
Chris@0 18 use Symfony\Component\Finder\Iterator\DepthRangeFilterIterator;
Chris@0 19 use Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator;
Chris@0 20 use Symfony\Component\Finder\Iterator\FilecontentFilterIterator;
Chris@0 21 use Symfony\Component\Finder\Iterator\FilenameFilterIterator;
Chris@0 22 use Symfony\Component\Finder\Iterator\SizeRangeFilterIterator;
Chris@0 23 use Symfony\Component\Finder\Iterator\SortableIterator;
Chris@0 24
Chris@0 25 /**
Chris@0 26 * Finder allows to build rules to find files and directories.
Chris@0 27 *
Chris@0 28 * It is a thin wrapper around several specialized iterator classes.
Chris@0 29 *
Chris@0 30 * All rules may be invoked several times.
Chris@0 31 *
Chris@0 32 * All methods return the current Finder object to allow easy chaining:
Chris@0 33 *
Chris@0 34 * $finder = Finder::create()->files()->name('*.php')->in(__DIR__);
Chris@0 35 *
Chris@0 36 * @author Fabien Potencier <fabien@symfony.com>
Chris@0 37 */
Chris@0 38 class Finder implements \IteratorAggregate, \Countable
Chris@0 39 {
Chris@0 40 const IGNORE_VCS_FILES = 1;
Chris@0 41 const IGNORE_DOT_FILES = 2;
Chris@0 42
Chris@0 43 private $mode = 0;
Chris@0 44 private $names = array();
Chris@0 45 private $notNames = array();
Chris@0 46 private $exclude = array();
Chris@0 47 private $filters = array();
Chris@0 48 private $depths = array();
Chris@0 49 private $sizes = array();
Chris@0 50 private $followLinks = false;
Chris@0 51 private $sort = false;
Chris@0 52 private $ignore = 0;
Chris@0 53 private $dirs = array();
Chris@0 54 private $dates = array();
Chris@0 55 private $iterators = array();
Chris@0 56 private $contains = array();
Chris@0 57 private $notContains = array();
Chris@0 58 private $paths = array();
Chris@0 59 private $notPaths = array();
Chris@0 60 private $ignoreUnreadableDirs = false;
Chris@0 61
Chris@0 62 private static $vcsPatterns = array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg');
Chris@0 63
Chris@0 64 public function __construct()
Chris@0 65 {
Chris@0 66 $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES;
Chris@0 67 }
Chris@0 68
Chris@0 69 /**
Chris@0 70 * Creates a new Finder.
Chris@0 71 *
Chris@0 72 * @return static
Chris@0 73 */
Chris@0 74 public static function create()
Chris@0 75 {
Chris@0 76 return new static();
Chris@0 77 }
Chris@0 78
Chris@0 79 /**
Chris@0 80 * Restricts the matching to directories only.
Chris@0 81 *
Chris@0 82 * @return $this
Chris@0 83 */
Chris@0 84 public function directories()
Chris@0 85 {
Chris@0 86 $this->mode = Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES;
Chris@0 87
Chris@0 88 return $this;
Chris@0 89 }
Chris@0 90
Chris@0 91 /**
Chris@0 92 * Restricts the matching to files only.
Chris@0 93 *
Chris@0 94 * @return $this
Chris@0 95 */
Chris@0 96 public function files()
Chris@0 97 {
Chris@0 98 $this->mode = Iterator\FileTypeFilterIterator::ONLY_FILES;
Chris@0 99
Chris@0 100 return $this;
Chris@0 101 }
Chris@0 102
Chris@0 103 /**
Chris@0 104 * Adds tests for the directory depth.
Chris@0 105 *
Chris@0 106 * Usage:
Chris@0 107 *
Chris@0 108 * $finder->depth('> 1') // the Finder will start matching at level 1.
Chris@0 109 * $finder->depth('< 3') // the Finder will descend at most 3 levels of directories below the starting point.
Chris@0 110 *
Chris@0 111 * @param string|int $level The depth level expression
Chris@0 112 *
Chris@0 113 * @return $this
Chris@0 114 *
Chris@0 115 * @see DepthRangeFilterIterator
Chris@0 116 * @see NumberComparator
Chris@0 117 */
Chris@0 118 public function depth($level)
Chris@0 119 {
Chris@0 120 $this->depths[] = new Comparator\NumberComparator($level);
Chris@0 121
Chris@0 122 return $this;
Chris@0 123 }
Chris@0 124
Chris@0 125 /**
Chris@0 126 * Adds tests for file dates (last modified).
Chris@0 127 *
Chris@0 128 * The date must be something that strtotime() is able to parse:
Chris@0 129 *
Chris@0 130 * $finder->date('since yesterday');
Chris@0 131 * $finder->date('until 2 days ago');
Chris@0 132 * $finder->date('> now - 2 hours');
Chris@0 133 * $finder->date('>= 2005-10-15');
Chris@0 134 *
Chris@0 135 * @param string $date A date range string
Chris@0 136 *
Chris@0 137 * @return $this
Chris@0 138 *
Chris@0 139 * @see strtotime
Chris@0 140 * @see DateRangeFilterIterator
Chris@0 141 * @see DateComparator
Chris@0 142 */
Chris@0 143 public function date($date)
Chris@0 144 {
Chris@0 145 $this->dates[] = new Comparator\DateComparator($date);
Chris@0 146
Chris@0 147 return $this;
Chris@0 148 }
Chris@0 149
Chris@0 150 /**
Chris@0 151 * Adds rules that files must match.
Chris@0 152 *
Chris@0 153 * You can use patterns (delimited with / sign), globs or simple strings.
Chris@0 154 *
Chris@0 155 * $finder->name('*.php')
Chris@0 156 * $finder->name('/\.php$/') // same as above
Chris@0 157 * $finder->name('test.php')
Chris@0 158 *
Chris@0 159 * @param string $pattern A pattern (a regexp, a glob, or a string)
Chris@0 160 *
Chris@0 161 * @return $this
Chris@0 162 *
Chris@0 163 * @see FilenameFilterIterator
Chris@0 164 */
Chris@0 165 public function name($pattern)
Chris@0 166 {
Chris@0 167 $this->names[] = $pattern;
Chris@0 168
Chris@0 169 return $this;
Chris@0 170 }
Chris@0 171
Chris@0 172 /**
Chris@0 173 * Adds rules that files must not match.
Chris@0 174 *
Chris@0 175 * @param string $pattern A pattern (a regexp, a glob, or a string)
Chris@0 176 *
Chris@0 177 * @return $this
Chris@0 178 *
Chris@0 179 * @see FilenameFilterIterator
Chris@0 180 */
Chris@0 181 public function notName($pattern)
Chris@0 182 {
Chris@0 183 $this->notNames[] = $pattern;
Chris@0 184
Chris@0 185 return $this;
Chris@0 186 }
Chris@0 187
Chris@0 188 /**
Chris@0 189 * Adds tests that file contents must match.
Chris@0 190 *
Chris@0 191 * Strings or PCRE patterns can be used:
Chris@0 192 *
Chris@0 193 * $finder->contains('Lorem ipsum')
Chris@0 194 * $finder->contains('/Lorem ipsum/i')
Chris@0 195 *
Chris@0 196 * @param string $pattern A pattern (string or regexp)
Chris@0 197 *
Chris@0 198 * @return $this
Chris@0 199 *
Chris@0 200 * @see FilecontentFilterIterator
Chris@0 201 */
Chris@0 202 public function contains($pattern)
Chris@0 203 {
Chris@0 204 $this->contains[] = $pattern;
Chris@0 205
Chris@0 206 return $this;
Chris@0 207 }
Chris@0 208
Chris@0 209 /**
Chris@0 210 * Adds tests that file contents must not match.
Chris@0 211 *
Chris@0 212 * Strings or PCRE patterns can be used:
Chris@0 213 *
Chris@0 214 * $finder->notContains('Lorem ipsum')
Chris@0 215 * $finder->notContains('/Lorem ipsum/i')
Chris@0 216 *
Chris@0 217 * @param string $pattern A pattern (string or regexp)
Chris@0 218 *
Chris@0 219 * @return $this
Chris@0 220 *
Chris@0 221 * @see FilecontentFilterIterator
Chris@0 222 */
Chris@0 223 public function notContains($pattern)
Chris@0 224 {
Chris@0 225 $this->notContains[] = $pattern;
Chris@0 226
Chris@0 227 return $this;
Chris@0 228 }
Chris@0 229
Chris@0 230 /**
Chris@0 231 * Adds rules that filenames must match.
Chris@0 232 *
Chris@0 233 * You can use patterns (delimited with / sign) or simple strings.
Chris@0 234 *
Chris@0 235 * $finder->path('some/special/dir')
Chris@0 236 * $finder->path('/some\/special\/dir/') // same as above
Chris@0 237 *
Chris@0 238 * Use only / as dirname separator.
Chris@0 239 *
Chris@0 240 * @param string $pattern A pattern (a regexp or a string)
Chris@0 241 *
Chris@0 242 * @return $this
Chris@0 243 *
Chris@0 244 * @see FilenameFilterIterator
Chris@0 245 */
Chris@0 246 public function path($pattern)
Chris@0 247 {
Chris@0 248 $this->paths[] = $pattern;
Chris@0 249
Chris@0 250 return $this;
Chris@0 251 }
Chris@0 252
Chris@0 253 /**
Chris@0 254 * Adds rules that filenames must not match.
Chris@0 255 *
Chris@0 256 * You can use patterns (delimited with / sign) or simple strings.
Chris@0 257 *
Chris@0 258 * $finder->notPath('some/special/dir')
Chris@0 259 * $finder->notPath('/some\/special\/dir/') // same as above
Chris@0 260 *
Chris@0 261 * Use only / as dirname separator.
Chris@0 262 *
Chris@0 263 * @param string $pattern A pattern (a regexp or a string)
Chris@0 264 *
Chris@0 265 * @return $this
Chris@0 266 *
Chris@0 267 * @see FilenameFilterIterator
Chris@0 268 */
Chris@0 269 public function notPath($pattern)
Chris@0 270 {
Chris@0 271 $this->notPaths[] = $pattern;
Chris@0 272
Chris@0 273 return $this;
Chris@0 274 }
Chris@0 275
Chris@0 276 /**
Chris@0 277 * Adds tests for file sizes.
Chris@0 278 *
Chris@0 279 * $finder->size('> 10K');
Chris@0 280 * $finder->size('<= 1Ki');
Chris@0 281 * $finder->size(4);
Chris@0 282 *
Chris@0 283 * @param string|int $size A size range string or an integer
Chris@0 284 *
Chris@0 285 * @return $this
Chris@0 286 *
Chris@0 287 * @see SizeRangeFilterIterator
Chris@0 288 * @see NumberComparator
Chris@0 289 */
Chris@0 290 public function size($size)
Chris@0 291 {
Chris@0 292 $this->sizes[] = new Comparator\NumberComparator($size);
Chris@0 293
Chris@0 294 return $this;
Chris@0 295 }
Chris@0 296
Chris@0 297 /**
Chris@0 298 * Excludes directories.
Chris@0 299 *
Chris@0 300 * @param string|array $dirs A directory path or an array of directories
Chris@0 301 *
Chris@0 302 * @return $this
Chris@0 303 *
Chris@0 304 * @see ExcludeDirectoryFilterIterator
Chris@0 305 */
Chris@0 306 public function exclude($dirs)
Chris@0 307 {
Chris@0 308 $this->exclude = array_merge($this->exclude, (array) $dirs);
Chris@0 309
Chris@0 310 return $this;
Chris@0 311 }
Chris@0 312
Chris@0 313 /**
Chris@0 314 * Excludes "hidden" directories and files (starting with a dot).
Chris@0 315 *
Chris@0 316 * @param bool $ignoreDotFiles Whether to exclude "hidden" files or not
Chris@0 317 *
Chris@0 318 * @return $this
Chris@0 319 *
Chris@0 320 * @see ExcludeDirectoryFilterIterator
Chris@0 321 */
Chris@0 322 public function ignoreDotFiles($ignoreDotFiles)
Chris@0 323 {
Chris@0 324 if ($ignoreDotFiles) {
Chris@0 325 $this->ignore |= static::IGNORE_DOT_FILES;
Chris@0 326 } else {
Chris@0 327 $this->ignore &= ~static::IGNORE_DOT_FILES;
Chris@0 328 }
Chris@0 329
Chris@0 330 return $this;
Chris@0 331 }
Chris@0 332
Chris@0 333 /**
Chris@0 334 * Forces the finder to ignore version control directories.
Chris@0 335 *
Chris@0 336 * @param bool $ignoreVCS Whether to exclude VCS files or not
Chris@0 337 *
Chris@0 338 * @return $this
Chris@0 339 *
Chris@0 340 * @see ExcludeDirectoryFilterIterator
Chris@0 341 */
Chris@0 342 public function ignoreVCS($ignoreVCS)
Chris@0 343 {
Chris@0 344 if ($ignoreVCS) {
Chris@0 345 $this->ignore |= static::IGNORE_VCS_FILES;
Chris@0 346 } else {
Chris@0 347 $this->ignore &= ~static::IGNORE_VCS_FILES;
Chris@0 348 }
Chris@0 349
Chris@0 350 return $this;
Chris@0 351 }
Chris@0 352
Chris@0 353 /**
Chris@0 354 * Adds VCS patterns.
Chris@0 355 *
Chris@0 356 * @see ignoreVCS()
Chris@0 357 *
Chris@0 358 * @param string|string[] $pattern VCS patterns to ignore
Chris@0 359 */
Chris@0 360 public static function addVCSPattern($pattern)
Chris@0 361 {
Chris@0 362 foreach ((array) $pattern as $p) {
Chris@0 363 self::$vcsPatterns[] = $p;
Chris@0 364 }
Chris@0 365
Chris@0 366 self::$vcsPatterns = array_unique(self::$vcsPatterns);
Chris@0 367 }
Chris@0 368
Chris@0 369 /**
Chris@0 370 * Sorts files and directories by an anonymous function.
Chris@0 371 *
Chris@0 372 * The anonymous function receives two \SplFileInfo instances to compare.
Chris@0 373 *
Chris@0 374 * This can be slow as all the matching files and directories must be retrieved for comparison.
Chris@0 375 *
Chris@0 376 * @return $this
Chris@0 377 *
Chris@0 378 * @see SortableIterator
Chris@0 379 */
Chris@0 380 public function sort(\Closure $closure)
Chris@0 381 {
Chris@0 382 $this->sort = $closure;
Chris@0 383
Chris@0 384 return $this;
Chris@0 385 }
Chris@0 386
Chris@0 387 /**
Chris@0 388 * Sorts files and directories by name.
Chris@0 389 *
Chris@0 390 * This can be slow as all the matching files and directories must be retrieved for comparison.
Chris@0 391 *
Chris@0 392 * @return $this
Chris@0 393 *
Chris@0 394 * @see SortableIterator
Chris@0 395 */
Chris@0 396 public function sortByName()
Chris@0 397 {
Chris@0 398 $this->sort = Iterator\SortableIterator::SORT_BY_NAME;
Chris@0 399
Chris@0 400 return $this;
Chris@0 401 }
Chris@0 402
Chris@0 403 /**
Chris@0 404 * Sorts files and directories by type (directories before files), then by name.
Chris@0 405 *
Chris@0 406 * This can be slow as all the matching files and directories must be retrieved for comparison.
Chris@0 407 *
Chris@0 408 * @return $this
Chris@0 409 *
Chris@0 410 * @see SortableIterator
Chris@0 411 */
Chris@0 412 public function sortByType()
Chris@0 413 {
Chris@0 414 $this->sort = Iterator\SortableIterator::SORT_BY_TYPE;
Chris@0 415
Chris@0 416 return $this;
Chris@0 417 }
Chris@0 418
Chris@0 419 /**
Chris@0 420 * Sorts files and directories by the last accessed time.
Chris@0 421 *
Chris@0 422 * This is the time that the file was last accessed, read or written to.
Chris@0 423 *
Chris@0 424 * This can be slow as all the matching files and directories must be retrieved for comparison.
Chris@0 425 *
Chris@0 426 * @return $this
Chris@0 427 *
Chris@0 428 * @see SortableIterator
Chris@0 429 */
Chris@0 430 public function sortByAccessedTime()
Chris@0 431 {
Chris@0 432 $this->sort = Iterator\SortableIterator::SORT_BY_ACCESSED_TIME;
Chris@0 433
Chris@0 434 return $this;
Chris@0 435 }
Chris@0 436
Chris@0 437 /**
Chris@0 438 * Sorts files and directories by the last inode changed time.
Chris@0 439 *
Chris@0 440 * This is the time that the inode information was last modified (permissions, owner, group or other metadata).
Chris@0 441 *
Chris@0 442 * On Windows, since inode is not available, changed time is actually the file creation time.
Chris@0 443 *
Chris@0 444 * This can be slow as all the matching files and directories must be retrieved for comparison.
Chris@0 445 *
Chris@0 446 * @return $this
Chris@0 447 *
Chris@0 448 * @see SortableIterator
Chris@0 449 */
Chris@0 450 public function sortByChangedTime()
Chris@0 451 {
Chris@0 452 $this->sort = Iterator\SortableIterator::SORT_BY_CHANGED_TIME;
Chris@0 453
Chris@0 454 return $this;
Chris@0 455 }
Chris@0 456
Chris@0 457 /**
Chris@0 458 * Sorts files and directories by the last modified time.
Chris@0 459 *
Chris@0 460 * This is the last time the actual contents of the file were last modified.
Chris@0 461 *
Chris@0 462 * This can be slow as all the matching files and directories must be retrieved for comparison.
Chris@0 463 *
Chris@0 464 * @return $this
Chris@0 465 *
Chris@0 466 * @see SortableIterator
Chris@0 467 */
Chris@0 468 public function sortByModifiedTime()
Chris@0 469 {
Chris@0 470 $this->sort = Iterator\SortableIterator::SORT_BY_MODIFIED_TIME;
Chris@0 471
Chris@0 472 return $this;
Chris@0 473 }
Chris@0 474
Chris@0 475 /**
Chris@0 476 * Filters the iterator with an anonymous function.
Chris@0 477 *
Chris@0 478 * The anonymous function receives a \SplFileInfo and must return false
Chris@0 479 * to remove files.
Chris@0 480 *
Chris@0 481 * @return $this
Chris@0 482 *
Chris@0 483 * @see CustomFilterIterator
Chris@0 484 */
Chris@0 485 public function filter(\Closure $closure)
Chris@0 486 {
Chris@0 487 $this->filters[] = $closure;
Chris@0 488
Chris@0 489 return $this;
Chris@0 490 }
Chris@0 491
Chris@0 492 /**
Chris@0 493 * Forces the following of symlinks.
Chris@0 494 *
Chris@0 495 * @return $this
Chris@0 496 */
Chris@0 497 public function followLinks()
Chris@0 498 {
Chris@0 499 $this->followLinks = true;
Chris@0 500
Chris@0 501 return $this;
Chris@0 502 }
Chris@0 503
Chris@0 504 /**
Chris@0 505 * Tells finder to ignore unreadable directories.
Chris@0 506 *
Chris@0 507 * By default, scanning unreadable directories content throws an AccessDeniedException.
Chris@0 508 *
Chris@0 509 * @param bool $ignore
Chris@0 510 *
Chris@0 511 * @return $this
Chris@0 512 */
Chris@0 513 public function ignoreUnreadableDirs($ignore = true)
Chris@0 514 {
Chris@0 515 $this->ignoreUnreadableDirs = (bool) $ignore;
Chris@0 516
Chris@0 517 return $this;
Chris@0 518 }
Chris@0 519
Chris@0 520 /**
Chris@0 521 * Searches files and directories which match defined rules.
Chris@0 522 *
Chris@0 523 * @param string|array $dirs A directory path or an array of directories
Chris@0 524 *
Chris@0 525 * @return $this
Chris@0 526 *
Chris@0 527 * @throws \InvalidArgumentException if one of the directories does not exist
Chris@0 528 */
Chris@0 529 public function in($dirs)
Chris@0 530 {
Chris@0 531 $resolvedDirs = array();
Chris@0 532
Chris@0 533 foreach ((array) $dirs as $dir) {
Chris@0 534 if (is_dir($dir)) {
Chris@0 535 $resolvedDirs[] = $dir;
Chris@0 536 } elseif ($glob = glob($dir, (defined('GLOB_BRACE') ? GLOB_BRACE : 0) | GLOB_ONLYDIR)) {
Chris@0 537 $resolvedDirs = array_merge($resolvedDirs, $glob);
Chris@0 538 } else {
Chris@0 539 throw new \InvalidArgumentException(sprintf('The "%s" directory does not exist.', $dir));
Chris@0 540 }
Chris@0 541 }
Chris@0 542
Chris@0 543 $this->dirs = array_merge($this->dirs, $resolvedDirs);
Chris@0 544
Chris@0 545 return $this;
Chris@0 546 }
Chris@0 547
Chris@0 548 /**
Chris@0 549 * Returns an Iterator for the current Finder configuration.
Chris@0 550 *
Chris@0 551 * This method implements the IteratorAggregate interface.
Chris@0 552 *
Chris@0 553 * @return \Iterator|SplFileInfo[] An iterator
Chris@0 554 *
Chris@0 555 * @throws \LogicException if the in() method has not been called
Chris@0 556 */
Chris@0 557 public function getIterator()
Chris@0 558 {
Chris@0 559 if (0 === count($this->dirs) && 0 === count($this->iterators)) {
Chris@0 560 throw new \LogicException('You must call one of in() or append() methods before iterating over a Finder.');
Chris@0 561 }
Chris@0 562
Chris@0 563 if (1 === count($this->dirs) && 0 === count($this->iterators)) {
Chris@0 564 return $this->searchInDirectory($this->dirs[0]);
Chris@0 565 }
Chris@0 566
Chris@0 567 $iterator = new \AppendIterator();
Chris@0 568 foreach ($this->dirs as $dir) {
Chris@0 569 $iterator->append($this->searchInDirectory($dir));
Chris@0 570 }
Chris@0 571
Chris@0 572 foreach ($this->iterators as $it) {
Chris@0 573 $iterator->append($it);
Chris@0 574 }
Chris@0 575
Chris@0 576 return $iterator;
Chris@0 577 }
Chris@0 578
Chris@0 579 /**
Chris@0 580 * Appends an existing set of files/directories to the finder.
Chris@0 581 *
Chris@0 582 * The set can be another Finder, an Iterator, an IteratorAggregate, or even a plain array.
Chris@0 583 *
Chris@0 584 * @param mixed $iterator
Chris@0 585 *
Chris@0 586 * @return $this
Chris@0 587 *
Chris@0 588 * @throws \InvalidArgumentException when the given argument is not iterable
Chris@0 589 */
Chris@0 590 public function append($iterator)
Chris@0 591 {
Chris@0 592 if ($iterator instanceof \IteratorAggregate) {
Chris@0 593 $this->iterators[] = $iterator->getIterator();
Chris@0 594 } elseif ($iterator instanceof \Iterator) {
Chris@0 595 $this->iterators[] = $iterator;
Chris@0 596 } elseif ($iterator instanceof \Traversable || is_array($iterator)) {
Chris@0 597 $it = new \ArrayIterator();
Chris@0 598 foreach ($iterator as $file) {
Chris@0 599 $it->append($file instanceof \SplFileInfo ? $file : new \SplFileInfo($file));
Chris@0 600 }
Chris@0 601 $this->iterators[] = $it;
Chris@0 602 } else {
Chris@0 603 throw new \InvalidArgumentException('Finder::append() method wrong argument type.');
Chris@0 604 }
Chris@0 605
Chris@0 606 return $this;
Chris@0 607 }
Chris@0 608
Chris@0 609 /**
Chris@0 610 * Counts all the results collected by the iterators.
Chris@0 611 *
Chris@0 612 * @return int
Chris@0 613 */
Chris@0 614 public function count()
Chris@0 615 {
Chris@0 616 return iterator_count($this->getIterator());
Chris@0 617 }
Chris@0 618
Chris@0 619 /**
Chris@0 620 * @param $dir
Chris@0 621 *
Chris@0 622 * @return \Iterator
Chris@0 623 */
Chris@0 624 private function searchInDirectory($dir)
Chris@0 625 {
Chris@0 626 if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) {
Chris@0 627 $this->exclude = array_merge($this->exclude, self::$vcsPatterns);
Chris@0 628 }
Chris@0 629
Chris@0 630 if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) {
Chris@0 631 $this->notPaths[] = '#(^|/)\..+(/|$)#';
Chris@0 632 }
Chris@0 633
Chris@0 634 $minDepth = 0;
Chris@0 635 $maxDepth = PHP_INT_MAX;
Chris@0 636
Chris@0 637 foreach ($this->depths as $comparator) {
Chris@0 638 switch ($comparator->getOperator()) {
Chris@0 639 case '>':
Chris@0 640 $minDepth = $comparator->getTarget() + 1;
Chris@0 641 break;
Chris@0 642 case '>=':
Chris@0 643 $minDepth = $comparator->getTarget();
Chris@0 644 break;
Chris@0 645 case '<':
Chris@0 646 $maxDepth = $comparator->getTarget() - 1;
Chris@0 647 break;
Chris@0 648 case '<=':
Chris@0 649 $maxDepth = $comparator->getTarget();
Chris@0 650 break;
Chris@0 651 default:
Chris@0 652 $minDepth = $maxDepth = $comparator->getTarget();
Chris@0 653 }
Chris@0 654 }
Chris@0 655
Chris@0 656 $flags = \RecursiveDirectoryIterator::SKIP_DOTS;
Chris@0 657
Chris@0 658 if ($this->followLinks) {
Chris@0 659 $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
Chris@0 660 }
Chris@0 661
Chris@0 662 $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs);
Chris@0 663
Chris@0 664 if ($this->exclude) {
Chris@0 665 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
Chris@0 666 }
Chris@0 667
Chris@0 668 $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
Chris@0 669
Chris@0 670 if ($minDepth > 0 || $maxDepth < PHP_INT_MAX) {
Chris@0 671 $iterator = new Iterator\DepthRangeFilterIterator($iterator, $minDepth, $maxDepth);
Chris@0 672 }
Chris@0 673
Chris@0 674 if ($this->mode) {
Chris@0 675 $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode);
Chris@0 676 }
Chris@0 677
Chris@0 678 if ($this->names || $this->notNames) {
Chris@0 679 $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames);
Chris@0 680 }
Chris@0 681
Chris@0 682 if ($this->contains || $this->notContains) {
Chris@0 683 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
Chris@0 684 }
Chris@0 685
Chris@0 686 if ($this->sizes) {
Chris@0 687 $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes);
Chris@0 688 }
Chris@0 689
Chris@0 690 if ($this->dates) {
Chris@0 691 $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates);
Chris@0 692 }
Chris@0 693
Chris@0 694 if ($this->filters) {
Chris@0 695 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
Chris@0 696 }
Chris@0 697
Chris@0 698 if ($this->paths || $this->notPaths) {
Chris@0 699 $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths);
Chris@0 700 }
Chris@0 701
Chris@0 702 if ($this->sort) {
Chris@0 703 $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
Chris@0 704 $iterator = $iteratorAggregate->getIterator();
Chris@0 705 }
Chris@0 706
Chris@0 707 return $iterator;
Chris@0 708 }
Chris@0 709 }