Passed
Push — 0.8.x ( 292ed1...b9fea5 )
by Alexander
07:26 queued 03:54
created

Finder::count()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
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 not of files.
84
     * 
85
     * @var array $notPaths
86
     */
87
    private array $notPaths = [];
88
89
    /**
90
     * Get the path of file.
91
     * 
92
     * @var array $paths
93
     */
94
    private array $paths = [];
95
96
    /**
97
     * Constructor. Create a new Finder class instance.
98
     * 
99
     * @return void
100
     */
101
    public function __construct()
102
    {
103
        $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES;
104
    }
105
    
106
    /* Creates a new Finder instance.
107
     * 
108
     * @return static
109
     */
110
    public static function create(): static
111
    {
112
        return new static();
113
    }
114
115
    /**
116
     * Restricts the matching to files only.
117
     * 
118
     * @return static
119
     */
120
    public function files(): static
121
    {
122
        $this->mode = FileFilterIterator::ONLY_FILES;
123
124
        return $this;
125
    }
126
127
    /**
128
     * Adds filters for file dates (last modified).
129
     * 
130
     * @param  string|string[]  $dates
131
     * 
132
     * @return static
133
     */
134
    public function date(string|array $dates): static
135
    {
136
        foreach ((array) $dates as $date) {
137
            $this->dates[] = new DateComparator($date);
138
        }
139
140
        return $this;
141
    }
142
    
143
    /**
144
     * Adds rules that filenames must match.
145
     * 
146
     * @param  string|string[]  $patterns
147
     * 
148
     * @return static
149
     */
150
    public function path(string|array $patterns): static
151
    {
152
        $this->paths = array_merge($this->paths, (array) $patterns);
153
        
154
        return $this;
155
    }
156
    
157
    /**
158
     * Adds rules that filenames must not match.
159
     * 
160
     * @param  string|string[]
161
     * 
162
     * @return static
163
     */
164
    public function notPath(string|array $patterns): static
165
    {
166
        $this->notPaths = array_merge($this->notPaths, (array) $patterns);
167
        
168
        return $this;
169
    }
170
171
    /**
172
     * Excludes "hidden" directories and files (starting with a dot).
173
     * 
174
     * @param  bool  $ignore
175
     * 
176
     * @return static
177
     */
178
    public function ignoreDotFiles(bool $ignore): static
179
    {
180
        if ($ignore) {
181
            $this->ignore |= static::IGNORE_DOT_FILES;
182
        } else {
183
            $this->ignore &= ~static::IGNORE_VCS_FILES;
184
        }
185
186
        return $this;
187
    }
188
    
189
    /**
190
     * Searches files and directories which match defined rules.
191
     * 
192
     * @param  string|string[]  $dirs  A directory path or an array of directories
193
     * 
194
     * @return static
195
     * 
196
     * @throws DirectoryNotFoundException  if one of the directories does not exist
197
     */
198
    public function in(string|array $dirs): static
199
    {
200
        $resolvedDirs = [];
201
        
202
        foreach ((array) $dirs as $dir) {
203
            if (is_dir($dir)) {
204
                $resolvedDirs[] = [$this->normalizeDir($dir)];
205
            } elseif ($glob = glob($dir, (defined('GLOB_BRACE') ? GLOB_BRACE : 0) | GLOB_ONLYDIR | GLOB_NOSORT)) {
206
                sort($glob);
207
                
208
                $resolvedDirs[] = array_map($this->normalizeDir('...'), $glob);
209
            } else {
210
                throw new DirectoryNotFoundException(sprintf('The "%s" directory does not exist', $dir));
211
            }
212
        }
213
        
214
        $this->dirs = array_merge($this->dirs, ...$resolvedDirs);
215
        
216
        return $this;
217
    }
218
    
219
    /**
220
     * Counts all the results collected by the iterators.
221
     * 
222
     * @return int
223
     */
224
    public function count(): int
225
    {
226
        return iterator_count($this->getIterator());
227
    }
228
229
    /**
230
     * Retrieve an external iterator for the current Finder configuration.
231
     * 
232
     * @return \Iterator
233
     * 
234
     * @throws \LogicException
235
     */
236
    public function getIterator(): Traversable
237
    {
238
        if (0 === count($this->dirs)) {
239
            throw new LogicException('You must call one of in() or append() methods before iterating over a Finder');
240
        }
241
242
        if (1 === count($this->dirs)) {
243
            $iterator = $this->searchInDirectory($this->dirs[0]);
244
245
            return $iterator;
246
        }
247
248
        $iterator = new AppendIterator();
249
250
        foreach ($this->dirs as $dir) {
251
            $iterator->append(new IteratorIterator(
252
                new LazyFilterIterator(fn () => $this->searchInDirectory($dir)))
253
            );
254
        }
255
256
        return $iterator;
257
    }
258
}