Iterator.php 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. <?php declare(strict_types=1);
  2. /*
  3. * This file is part of phpunit/php-file-iterator.
  4. *
  5. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace SebastianBergmann\FileIterator;
  11. use function assert;
  12. use function preg_match;
  13. use function realpath;
  14. use function str_ends_with;
  15. use function str_replace;
  16. use function str_starts_with;
  17. use AppendIterator;
  18. use FilterIterator;
  19. use SplFileInfo;
  20. /**
  21. * @template-extends FilterIterator<int, string, AppendIterator>
  22. *
  23. * @internal This class is not covered by the backward compatibility promise for phpunit/php-file-iterator
  24. */
  25. final class Iterator extends FilterIterator
  26. {
  27. public const PREFIX = 0;
  28. public const SUFFIX = 1;
  29. private string|false $basePath;
  30. /**
  31. * @psalm-var list<string>
  32. */
  33. private array $suffixes;
  34. /**
  35. * @psalm-var list<string>
  36. */
  37. private array $prefixes;
  38. /**
  39. * @psalm-param list<string> $suffixes
  40. * @psalm-param list<string> $prefixes
  41. */
  42. public function __construct(string $basePath, \Iterator $iterator, array $suffixes = [], array $prefixes = [])
  43. {
  44. $this->basePath = realpath($basePath);
  45. $this->prefixes = $prefixes;
  46. $this->suffixes = $suffixes;
  47. parent::__construct($iterator);
  48. }
  49. public function accept(): bool
  50. {
  51. $current = $this->getInnerIterator()->current();
  52. assert($current instanceof SplFileInfo);
  53. $filename = $current->getFilename();
  54. $realPath = $current->getRealPath();
  55. if ($realPath === false) {
  56. // @codeCoverageIgnoreStart
  57. return false;
  58. // @codeCoverageIgnoreEnd
  59. }
  60. return $this->acceptPath($realPath) &&
  61. $this->acceptPrefix($filename) &&
  62. $this->acceptSuffix($filename);
  63. }
  64. private function acceptPath(string $path): bool
  65. {
  66. // Filter files in hidden directories by checking path that is relative to the base path.
  67. if (preg_match('=/\.[^/]*/=', str_replace((string) $this->basePath, '', $path))) {
  68. return false;
  69. }
  70. return true;
  71. }
  72. private function acceptPrefix(string $filename): bool
  73. {
  74. return $this->acceptSubString($filename, $this->prefixes, self::PREFIX);
  75. }
  76. private function acceptSuffix(string $filename): bool
  77. {
  78. return $this->acceptSubString($filename, $this->suffixes, self::SUFFIX);
  79. }
  80. /**
  81. * @psalm-param list<string> $subStrings
  82. */
  83. private function acceptSubString(string $filename, array $subStrings, int $type): bool
  84. {
  85. if (empty($subStrings)) {
  86. return true;
  87. }
  88. foreach ($subStrings as $string) {
  89. if (($type === self::PREFIX && str_starts_with($filename, $string)) ||
  90. ($type === self::SUFFIX && str_ends_with($filename, $string))) {
  91. return true;
  92. }
  93. }
  94. return false;
  95. }
  96. }