Passed
Push — 0.8.x ( 68625b...156d51 )
by Alexander
06:01 queued 03:01
created

Finder::in()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 11
c 1
b 0
f 0
nc 4
nop 1
dl 0
loc 19
rs 9.6111
1
<?php
2
3
/**
4
 * Lenevor Framework
5
 *
6
 * LICENSE
7
 *
8
 * This source file is subject to the new BSD license that is bundled
9
 * with this package in the file license.md.
10
 * It is also available through the world-wide-web at this URL:
11
 * https://lenevor.com/license
12
 * If you did not receive a copy of the license and are unable to
13
 * obtain it through the world-wide-web, please send an email
14
 * to [email protected] so we can send you a copy immediately.
15
 *
16
 * @package     Lenevor
17
 * @subpackage  Base
18
 * @link        https://lenevor.com
19
 * @copyright   Copyright (c) 2019 - 2023 Alexander Campo <[email protected]>
20
 * @license     https://opensource.org/licenses/BSD-3-Clause New BSD license or see https://lenevor.com/license or see /license.md
21
 */
22
23
namespace Syscodes\Components\Finder;
24
25
use AppendIterator;
26
use Countable;
27
use Traversable;
28
use LogicException;
29
use IteratorIterator;
30
use IteratorAggregate;
31
use Syscodes\Components\Finder\Concerns\FinderHelper;
32
use Syscodes\Components\Finder\Comparators\DateComparator;
33
use Syscodes\Components\Finder\Filters\FileFilterIterator;
34
use Syscodes\Components\Finder\Exceptions\DirectoryNotFoundException;
35
use Syscodes\Components\Finder\Filters\LazyFilterIterator;
36
37
/**
38
 * Gets the results of search in files and directories.
39
 */
40
class Finder implements IteratorAggregate, Countable
41
{
42
    use FinderHelper;
43
44
    public const IGNORE_VCS_FILES = 1;
45
    public const IGNORE_DOT_FILES = 2;
46
47
    /**
48
     * Get the file date.
49
     * 
50
     * @var array $dates
51
     */
52
    private array $dates = [];
53
54
    /**
55
     * Get the directories.
56
     * 
57
     * @var array $dirs
58
     */
59
    private array $dirs = [];
60
61
    /**
62
     * Get ignore for given type file. 
63
     * 
64
     * @var int $ignore
65
     */
66
    private int $ignore = 0;
67
68
    /**
69
     * Get ignore dirs for given type file.
70
     * 
71
     * @var bool $ignoreDirs
72
     */
73
    private bool $ignoreDirs = false;
0 ignored issues
show
introduced by
The private property $ignoreDirs is not used, and could be removed.
Loading history...
74
75
    /**
76
     * Get the mode for file.
77
     * 
78
     * @var int $mode
79
     */
80
    private int $mode = 0;
81
82
    /**
83
     * Get the path of file.
84
     * 
85
     * @var array $paths
86
     */
87
    private array $paths = [];
88
89
    /**
90
     * Constructor. Create a new Finder class instance.
91
     * 
92
     * @return void
93
     */
94
    public function __construct()
95
    {
96
        $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES;
97
    }
98
    
99
    /* Creates a new Finder instance.
100
     * 
101
     * @return static
102
     */
103
    public static function create(): static
104
    {
105
        return new static();
106
    }
107
108
    /**
109
     * Restricts the matching to files only.
110
     * 
111
     * @return static
112
     */
113
    public function files(): static
114
    {
115
        $this->mode = FileFilterIterator::ONLY_FILES;
116
117
        return $this;
118
    }
119
120
    /**
121
     * Adds filters for file dates (last modified).
122
     * 
123
     * @param  string|string[]  $dates
124
     * 
125
     * @return static
126
     */
127
    public function date(string|array $dates): static
128
    {
129
        foreach ((array) $dates as $date) {
130
            $this->dates[] = new DateComparator($date);
131
        }
132
133
        return $this;
134
    }
135
    
136
    /**
137
     * Adds rules that filenames must match.
138
     * 
139
     * @param  string|string[]  $patterns
140
     * 
141
     * @return static
142
     */
143
    public function path(string|array $patterns): static
144
    {
145
        $this->paths = array_merge($this->paths, (array) $patterns);
146
        
147
        return $this;
148
    }
149
150
    /**
151
     * Excludes "hidden" directories and files (starting with a dot).
152
     * 
153
     * @param  bool  $ignore
154
     * 
155
     * @return static
156
     */
157
    public function ignoreDotFiles(bool $ignore): static
158
    {
159
        if ($ignore) {
160
            $this->ignore |= static::IGNORE_DOT_FILES;
161
        } else {
162
            $this->ignore &= ~static::IGNORE_VCS_FILES;
163
        }
164
165
        return $this;
166
    }
167
    
168
    /**
169
     * Searches files and directories which match defined rules.
170
     * 
171
     * @param  string|string[]  $dirs  A directory path or an array of directories
172
     * 
173
     * @return static
174
     * 
175
     * @throws DirectoryNotFoundException  if one of the directories does not exist
176
     */
177
    public function in(string|array $dirs): static
178
    {
179
        $resolvedDirs = [];
180
        
181
        foreach ((array) $dirs as $dir) {
182
            if (is_dir($dir)) {
183
                $resolvedDirs[] = [$this->normalizeDir($dir)];
184
            } elseif ($glob = glob($dir, (defined('GLOB_BRACE') ? GLOB_BRACE : 0) | GLOB_ONLYDIR | GLOB_NOSORT)) {
185
                sort($glob);
186
                
187
                $resolvedDirs[] = array_map($this->normalizeDir('...'), $glob);
188
            } else {
189
                throw new DirectoryNotFoundException(sprintf('The "%s" directory does not exist', $dir));
190
            }
191
        }
192
        
193
        $this->dirs = array_merge($this->dirs, ...$resolvedDirs);
194
        
195
        return $this;
196
    }
197
    
198
    /**
199
     * Counts all the results collected by the iterators.
200
     * 
201
     * @return int
202
     */
203
    public function count(): int
204
    {
205
        return iterator_count($this->getIterator());
206
    }
207
208
    /**
209
     * Retrieve an external iterator for the current Finder configuration.
210
     * 
211
     * @return \Iterator
212
     * 
213
     * @throws \LogicException
214
     */
215
    public function getIterator(): Traversable
216
    {
217
        if (0 === count($this->dirs)) {
218
            throw new LogicException('You must call one of in() or append() methods before iterating over a Finder');
219
        }
220
221
        if (1 === count($this->dirs)) {
222
            $iterator = $this->searchInDirectory($this->dirs[0]);
223
224
            return $iterator;
225
        }
226
227
        $iterator = new AppendIterator();
228
229
        foreach ($this->dirs as $dir) {
230
            $iterator->append(new IteratorIterator(
231
                new LazyFilterIterator(fn () => $this->searchInDirectory($dir)))
232
            );
233
        }
234
235
        return $iterator;
236
    }
237
}