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 */
10namespace SebastianBergmann\FileIterator;
11
12use const GLOB_ONLYDIR;
13use function array_filter;
14use function array_map;
15use function array_merge;
16use function glob;
17use function is_dir;
18use function is_string;
19use function realpath;
20use AppendIterator;
21use RecursiveDirectoryIterator;
22use RecursiveIteratorIterator;
23
24class Factory
25{
26    /**
27     * @param array|string $paths
28     * @param array|string $suffixes
29     * @param array|string $prefixes
30     */
31    public function getFileIterator($paths, $suffixes = '', $prefixes = '', array $exclude = []): AppendIterator
32    {
33        if (is_string($paths)) {
34            $paths = [$paths];
35        }
36
37        $paths   = $this->getPathsAfterResolvingWildcards($paths);
38        $exclude = $this->getPathsAfterResolvingWildcards($exclude);
39
40        if (is_string($prefixes)) {
41            if ($prefixes !== '') {
42                $prefixes = [$prefixes];
43            } else {
44                $prefixes = [];
45            }
46        }
47
48        if (is_string($suffixes)) {
49            if ($suffixes !== '') {
50                $suffixes = [$suffixes];
51            } else {
52                $suffixes = [];
53            }
54        }
55
56        $iterator = new AppendIterator;
57
58        foreach ($paths as $path) {
59            if (is_dir($path)) {
60                $iterator->append(
61                    new Iterator(
62                        $path,
63                        new RecursiveIteratorIterator(
64                            new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::FOLLOW_SYMLINKS | RecursiveDirectoryIterator::SKIP_DOTS)
65                        ),
66                        $suffixes,
67                        $prefixes,
68                        $exclude
69                    )
70                );
71            }
72        }
73
74        return $iterator;
75    }
76
77    protected function getPathsAfterResolvingWildcards(array $paths): array
78    {
79        $_paths = [];
80
81        foreach ($paths as $path) {
82            if ($locals = glob($path, GLOB_ONLYDIR)) {
83                $_paths = array_merge($_paths, array_map('\realpath', $locals));
84            } else {
85                $_paths[] = realpath($path);
86            }
87        }
88
89        return array_filter($_paths);
90    }
91}
92