8889841cREADME.md 0000666 00000001073 15044176174 0006041 0 ustar 00 [](https://travis-ci.org/sebastianbergmann/php-file-iterator)
# php-file-iterator
## Installation
You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/):
composer require phpunit/php-file-iterator
If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency:
composer require --dev phpunit/php-file-iterator
src/Iterator.php 0000666 00000005634 15044176174 0007662 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\FileIterator;
use function array_filter;
use function array_map;
use function preg_match;
use function realpath;
use function str_replace;
use function strlen;
use function strpos;
use function substr;
use FilterIterator;
class Iterator extends FilterIterator
{
public const PREFIX = 0;
public const SUFFIX = 1;
/**
* @var string
*/
private $basePath;
/**
* @var array
*/
private $suffixes = [];
/**
* @var array
*/
private $prefixes = [];
/**
* @var array
*/
private $exclude = [];
public function __construct(string $basePath, \Iterator $iterator, array $suffixes = [], array $prefixes = [], array $exclude = [])
{
$this->basePath = realpath($basePath);
$this->prefixes = $prefixes;
$this->suffixes = $suffixes;
$this->exclude = array_filter(array_map('realpath', $exclude));
parent::__construct($iterator);
}
public function accept(): bool
{
$current = $this->getInnerIterator()->current();
$filename = $current->getFilename();
$realPath = $current->getRealPath();
if ($realPath === false) {
return false;
}
return $this->acceptPath($realPath) &&
$this->acceptPrefix($filename) &&
$this->acceptSuffix($filename);
}
private function acceptPath(string $path): bool
{
// Filter files in hidden directories by checking path that is relative to the base path.
if (preg_match('=/\.[^/]*/=', str_replace($this->basePath, '', $path))) {
return false;
}
foreach ($this->exclude as $exclude) {
if (strpos($path, $exclude) === 0) {
return false;
}
}
return true;
}
private function acceptPrefix(string $filename): bool
{
return $this->acceptSubString($filename, $this->prefixes, self::PREFIX);
}
private function acceptSuffix(string $filename): bool
{
return $this->acceptSubString($filename, $this->suffixes, self::SUFFIX);
}
private function acceptSubString(string $filename, array $subStrings, int $type): bool
{
if (empty($subStrings)) {
return true;
}
$matched = false;
foreach ($subStrings as $string) {
if (($type === self::PREFIX && strpos($filename, $string) === 0) ||
($type === self::SUFFIX &&
substr($filename, -1 * strlen($string)) === $string)) {
$matched = true;
break;
}
}
return $matched;
}
}
src/Factory.php 0000666 00000004702 15044176174 0007473 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\FileIterator;
use const GLOB_ONLYDIR;
use function array_filter;
use function array_map;
use function array_merge;
use function glob;
use function is_dir;
use function is_string;
use function realpath;
use AppendIterator;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
class Factory
{
/**
* @param array|string $paths
* @param array|string $suffixes
* @param array|string $prefixes
*/
public function getFileIterator($paths, $suffixes = '', $prefixes = '', array $exclude = []): AppendIterator
{
if (is_string($paths)) {
$paths = [$paths];
}
$paths = $this->getPathsAfterResolvingWildcards($paths);
$exclude = $this->getPathsAfterResolvingWildcards($exclude);
if (is_string($prefixes)) {
if ($prefixes !== '') {
$prefixes = [$prefixes];
} else {
$prefixes = [];
}
}
if (is_string($suffixes)) {
if ($suffixes !== '') {
$suffixes = [$suffixes];
} else {
$suffixes = [];
}
}
$iterator = new AppendIterator;
foreach ($paths as $path) {
if (is_dir($path)) {
$iterator->append(
new Iterator(
$path,
new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::FOLLOW_SYMLINKS | RecursiveDirectoryIterator::SKIP_DOTS)
),
$suffixes,
$prefixes,
$exclude
)
);
}
}
return $iterator;
}
protected function getPathsAfterResolvingWildcards(array $paths): array
{
$_paths = [[]];
foreach ($paths as $path) {
if ($locals = glob($path, GLOB_ONLYDIR)) {
$_paths[] = array_map('\realpath', $locals);
} else {
$_paths[] = [realpath($path)];
}
}
return array_filter(array_merge(...$_paths));
}
}
src/Facade.php 0000666 00000005145 15044176174 0007231 0 ustar 00
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\FileIterator;
use const DIRECTORY_SEPARATOR;
use function array_unique;
use function count;
use function dirname;
use function explode;
use function is_file;
use function is_string;
use function realpath;
use function sort;
class Facade
{
/**
* @param array|string $paths
* @param array|string $suffixes
* @param array|string $prefixes
*/
public function getFilesAsArray($paths, $suffixes = '', $prefixes = '', array $exclude = [], bool $commonPath = false): array
{
if (is_string($paths)) {
$paths = [$paths];
}
$iterator = (new Factory)->getFileIterator($paths, $suffixes, $prefixes, $exclude);
$files = [];
foreach ($iterator as $file) {
$file = $file->getRealPath();
if ($file) {
$files[] = $file;
}
}
foreach ($paths as $path) {
if (is_file($path)) {
$files[] = realpath($path);
}
}
$files = array_unique($files);
sort($files);
if ($commonPath) {
return [
'commonPath' => $this->getCommonPath($files),
'files' => $files,
];
}
return $files;
}
protected function getCommonPath(array $files): string
{
$count = count($files);
if ($count === 0) {
return '';
}
if ($count === 1) {
return dirname($files[0]) . DIRECTORY_SEPARATOR;
}
$_files = [];
foreach ($files as $file) {
$_files[] = $_fileParts = explode(DIRECTORY_SEPARATOR, $file);
if (empty($_fileParts[0])) {
$_fileParts[0] = DIRECTORY_SEPARATOR;
}
}
$common = '';
$done = false;
$j = 0;
$count--;
while (!$done) {
for ($i = 0; $i < $count; $i++) {
if ($_files[$i][$j] != $_files[$i + 1][$j]) {
$done = true;
break;
}
}
if (!$done) {
$common .= $_files[0][$j];
if ($j > 0) {
$common .= DIRECTORY_SEPARATOR;
}
}
$j++;
}
return DIRECTORY_SEPARATOR . $common;
}
}
ChangeLog.md 0000666 00000011224 15044176174 0006732 0 ustar 00 # Change Log
All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/).
## [3.0.6] - 2021-12-02
### Changed
* [#73](https://github.com/sebastianbergmann/php-file-iterator/pull/73): Micro performance improvements on parsing paths
## [3.0.5] - 2020-09-28
### Changed
* Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3`
## [3.0.4] - 2020-07-11
### Fixed
* [#67](https://github.com/sebastianbergmann/php-file-iterator/issues/67): `TypeError` in `SebastianBergmann\FileIterator\Iterator::accept()`
## [3.0.3] - 2020-06-26
### Added
* This component is now supported on PHP 8
## [3.0.2] - 2020-06-15
### Changed
* Tests etc. are now ignored for archive exports
## [3.0.1] - 2020-04-18
### Fixed
* [#64](https://github.com/sebastianbergmann/php-file-iterator/issues/64): Release tarball contains Composer PHAR
## [3.0.0] - 2020-02-07
### Removed
* This component is no longer supported on PHP 7.1 and PHP 7.2
## [2.0.5] - 2021-12-02
### Changed
* [#73](https://github.com/sebastianbergmann/php-file-iterator/pull/73): Micro performance improvements on parsing paths
### Fixed
* [#74](https://github.com/sebastianbergmann/php-file-iterator/pull/74): Document return type of `SebastianBergmann\FileIterator\Iterator::accept()` so that Symfony's `DebugClassLoader` does not trigger a deprecation warning
## [2.0.4] - 2021-07-19
### Changed
* Added `ReturnTypeWillChange` attribute to `SebastianBergmann\FileIterator\Iterator::accept()` because the return type of `\FilterIterator::accept()` will change in PHP 8.1
## [2.0.3] - 2020-11-30
### Changed
* Changed PHP version constraint in `composer.json` from `^7.1` to `>=7.1`
## [2.0.2] - 2018-09-13
### Fixed
* [#48](https://github.com/sebastianbergmann/php-file-iterator/issues/48): Excluding an array that contains false ends up excluding the current working directory
## [2.0.1] - 2018-06-11
### Fixed
* [#46](https://github.com/sebastianbergmann/php-file-iterator/issues/46): Regression with hidden parent directory
## [2.0.0] - 2018-05-28
### Fixed
* [#30](https://github.com/sebastianbergmann/php-file-iterator/issues/30): Exclude is not considered if it is a parent of the base path
### Changed
* This component now uses namespaces
### Removed
* This component is no longer supported on PHP 5.3, PHP 5.4, PHP 5.5, PHP 5.6, and PHP 7.0
## [1.4.5] - 2017-11-27
### Fixed
* [#37](https://github.com/sebastianbergmann/php-file-iterator/issues/37): Regression caused by fix for [#30](https://github.com/sebastianbergmann/php-file-iterator/issues/30)
## [1.4.4] - 2017-11-27
### Fixed
* [#30](https://github.com/sebastianbergmann/php-file-iterator/issues/30): Exclude is not considered if it is a parent of the base path
## [1.4.3] - 2017-11-25
### Fixed
* [#34](https://github.com/sebastianbergmann/php-file-iterator/issues/34): Factory should use canonical directory names
## [1.4.2] - 2016-11-26
No changes
## [1.4.1] - 2015-07-26
No changes
## 1.4.0 - 2015-04-02
### Added
* [#23](https://github.com/sebastianbergmann/php-file-iterator/pull/23): Added support for wildcards (glob) in exclude
[3.0.6]: https://github.com/sebastianbergmann/php-file-iterator/compare/3.0.5...3.0.6
[3.0.5]: https://github.com/sebastianbergmann/php-file-iterator/compare/3.0.4...3.0.5
[3.0.4]: https://github.com/sebastianbergmann/php-file-iterator/compare/3.0.3...3.0.4
[3.0.3]: https://github.com/sebastianbergmann/php-file-iterator/compare/3.0.2...3.0.3
[3.0.2]: https://github.com/sebastianbergmann/php-file-iterator/compare/3.0.1...3.0.2
[3.0.1]: https://github.com/sebastianbergmann/php-file-iterator/compare/3.0.0...3.0.1
[3.0.0]: https://github.com/sebastianbergmann/php-file-iterator/compare/2.0.5...3.0.0
[2.0.5]: https://github.com/sebastianbergmann/php-file-iterator/compare/2.0.4...2.0.5
[2.0.4]: https://github.com/sebastianbergmann/php-file-iterator/compare/2.0.3...2.0.4
[2.0.3]: https://github.com/sebastianbergmann/php-file-iterator/compare/2.0.2...2.0.3
[2.0.2]: https://github.com/sebastianbergmann/php-file-iterator/compare/2.0.1...2.0.2
[2.0.1]: https://github.com/sebastianbergmann/php-file-iterator/compare/2.0.0...2.0.1
[2.0.0]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4.5...2.0.0
[1.4.5]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4.4...1.4.5
[1.4.4]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4.3...1.4.4
[1.4.3]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4.2...1.4.3
[1.4.2]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4.1...1.4.2
[1.4.1]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4.0...1.4.1
.psalm/baseline.xml 0000666 00000000345 15044176174 0010261 0 ustar 00
current
.psalm/config.xml 0000666 00000000753 15044176174 0007747 0 ustar 00
composer.json 0000666 00000002043 15044176174 0007302 0 ustar 00 {
"name": "phpunit/php-file-iterator",
"description": "FilterIterator implementation that filters files based on a list of suffixes.",
"type": "library",
"keywords": [
"iterator",
"filesystem"
],
"homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
"license": "BSD-3-Clause",
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-file-iterator/issues"
},
"config": {
"platform": {
"php": "7.3.0"
},
"optimize-autoloader": true,
"sort-packages": true
},
"prefer-stable": true,
"require": {
"php": ">=7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.3"
},
"autoload": {
"classmap": [
"src/"
]
},
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
}
}
LICENSE 0000666 00000003020 15044176174 0005561 0 ustar 00 php-file-iterator
Copyright (c) 2009-2021, Sebastian Bergmann .
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of Sebastian Bergmann nor the names of his
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.