PluginProbe
WindPress – Tailwind CSS integration for WordPress / 3.0.2
WindPress – Tailwind CSS integration for WordPress v3.0.2
3.2.89 3.2.88 3.2.87 3.2.86 3.2.85 3.2.84 3.2.83 3.2.82 3.2.81 trunk 3.0.0 3.0.1 3.0.10 3.0.11 3.0.12 3.0.13 3.0.14 3.0.15 3.0.16 3.0.17 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 All 143 releases
windpress / vendor / symfony / finder / Finder.php

Finder.php in WindPress – Tailwind CSS integration for WordPress 3.0.2, at vendor/symfony/finder/Finder.php

708 lines 22.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11 namespace WindPressPackages\Symfony\Component\Finder;
12
13 use WindPressPackages\Symfony\Component\Finder\Comparator\DateComparator;
14 use WindPressPackages\Symfony\Component\Finder\Comparator\NumberComparator;
15 use WindPressPackages\Symfony\Component\Finder\Exception\DirectoryNotFoundException;
16 use WindPressPackages\Symfony\Component\Finder\Iterator\CustomFilterIterator;
17 use WindPressPackages\Symfony\Component\Finder\Iterator\DateRangeFilterIterator;
18 use WindPressPackages\Symfony\Component\Finder\Iterator\DepthRangeFilterIterator;
19 use WindPressPackages\Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator;
20 use WindPressPackages\Symfony\Component\Finder\Iterator\FilecontentFilterIterator;
21 use WindPressPackages\Symfony\Component\Finder\Iterator\FilenameFilterIterator;
22 use WindPressPackages\Symfony\Component\Finder\Iterator\LazyIterator;
23 use WindPressPackages\Symfony\Component\Finder\Iterator\SizeRangeFilterIterator;
24 use WindPressPackages\Symfony\Component\Finder\Iterator\SortableIterator;
25 /**
26 * Finder allows to build rules to find files and directories.
27 *
28 * It is a thin wrapper around several specialized iterator classes.
29 *
30 * All rules may be invoked several times.
31 *
32 * All methods return the current Finder object to allow chaining:
33 *
34 * $finder = Finder::create()->files()->name('*.php')->in(__DIR__);
35 *
36 * @author Fabien Potencier <fabien@symfony.com>
37 *
38 * @implements \IteratorAggregate<string, SplFileInfo>
39 */
40 class Finder implements \IteratorAggregate, \Countable
41 {
42 public const IGNORE_VCS_FILES = 1;
43 public const IGNORE_DOT_FILES = 2;
44 public const IGNORE_VCS_IGNORED_FILES = 4;
45 private $mode = 0;
46 private $names = [];
47 private $notNames = [];
48 private $exclude = [];
49 private $filters = [];
50 private $depths = [];
51 private $sizes = [];
52 private $followLinks = \false;
53 private $reverseSorting = \false;
54 private $sort = \false;
55 private $ignore = 0;
56 private $dirs = [];
57 private $dates = [];
58 private $iterators = [];
59 private $contains = [];
60 private $notContains = [];
61 private $paths = [];
62 private $notPaths = [];
63 private $ignoreUnreadableDirs = \false;
64 private static $vcsPatterns = ['.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg'];
65 public function __construct()
66 {
67 $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES;
68 }
69 /**
70 * Creates a new Finder.
71 *
72 * @return static
73 */
74 public static function create()
75 {
76 return new static();
77 }
78 /**
79 * Restricts the matching to directories only.
80 *
81 * @return $this
82 */
83 public function directories()
84 {
85 $this->mode = Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES;
86 return $this;
87 }
88 /**
89 * Restricts the matching to files only.
90 *
91 * @return $this
92 */
93 public function files()
94 {
95 $this->mode = Iterator\FileTypeFilterIterator::ONLY_FILES;
96 return $this;
97 }
98 /**
99 * Adds tests for the directory depth.
100 *
101 * Usage:
102 *
103 * $finder->depth('> 1') // the Finder will start matching at level 1.
104 * $finder->depth('< 3') // the Finder will descend at most 3 levels of directories below the starting point.
105 * $finder->depth(['>= 1', '< 3'])
106 *
107 * @param string|int|string[]|int[] $levels The depth level expression or an array of depth levels
108 *
109 * @return $this
110 *
111 * @see DepthRangeFilterIterator
112 * @see NumberComparator
113 */
114 public function depth($levels)
115 {
116 foreach ((array) $levels as $level) {
117 $this->depths[] = new Comparator\NumberComparator($level);
118 }
119 return $this;
120 }
121 /**
122 * Adds tests for file dates (last modified).
123 *
124 * The date must be something that strtotime() is able to parse:
125 *
126 * $finder->date('since yesterday');
127 * $finder->date('until 2 days ago');
128 * $finder->date('> now - 2 hours');
129 * $finder->date('>= 2005-10-15');
130 * $finder->date(['>= 2005-10-15', '<= 2006-05-27']);
131 *
132 * @param string|string[] $dates A date range string or an array of date ranges
133 *
134 * @return $this
135 *
136 * @see strtotime
137 * @see DateRangeFilterIterator
138 * @see DateComparator
139 */
140 public function date($dates)
141 {
142 foreach ((array) $dates as $date) {
143 $this->dates[] = new Comparator\DateComparator($date);
144 }
145 return $this;
146 }
147 /**
148 * Adds rules that files must match.
149 *
150 * You can use patterns (delimited with / sign), globs or simple strings.
151 *
152 * $finder->name('/\.php$/')
153 * $finder->name('*.php') // same as above, without dot files
154 * $finder->name('test.php')
155 * $finder->name(['test.py', 'test.php'])
156 *
157 * @param string|string[] $patterns A pattern (a regexp, a glob, or a string) or an array of patterns
158 *
159 * @return $this
160 *
161 * @see FilenameFilterIterator
162 */
163 public function name($patterns)
164 {
165 $this->names = array_merge($this->names, (array) $patterns);
166 return $this;
167 }
168 /**
169 * Adds rules that files must not match.
170 *
171 * @param string|string[] $patterns A pattern (a regexp, a glob, or a string) or an array of patterns
172 *
173 * @return $this
174 *
175 * @see FilenameFilterIterator
176 */
177 public function notName($patterns)
178 {
179 $this->notNames = array_merge($this->notNames, (array) $patterns);
180 return $this;
181 }
182 /**
183 * Adds tests that file contents must match.
184 *
185 * Strings or PCRE patterns can be used:
186 *
187 * $finder->contains('Lorem ipsum')
188 * $finder->contains('/Lorem ipsum/i')
189 * $finder->contains(['dolor', '/ipsum/i'])
190 *
191 * @param string|string[] $patterns A pattern (string or regexp) or an array of patterns
192 *
193 * @return $this
194 *
195 * @see FilecontentFilterIterator
196 */
197 public function contains($patterns)
198 {
199 $this->contains = array_merge($this->contains, (array) $patterns);
200 return $this;
201 }
202 /**
203 * Adds tests that file contents must not match.
204 *
205 * Strings or PCRE patterns can be used:
206 *
207 * $finder->notContains('Lorem ipsum')
208 * $finder->notContains('/Lorem ipsum/i')
209 * $finder->notContains(['lorem', '/dolor/i'])
210 *
211 * @param string|string[] $patterns A pattern (string or regexp) or an array of patterns
212 *
213 * @return $this
214 *
215 * @see FilecontentFilterIterator
216 */
217 public function notContains($patterns)
218 {
219 $this->notContains = array_merge($this->notContains, (array) $patterns);
220 return $this;
221 }
222 /**
223 * Adds rules that filenames must match.
224 *
225 * You can use patterns (delimited with / sign) or simple strings.
226 *
227 * $finder->path('some/special/dir')
228 * $finder->path('/some\/special\/dir/') // same as above
229 * $finder->path(['some dir', 'another/dir'])
230 *
231 * Use only / as dirname separator.
232 *
233 * @param string|string[] $patterns A pattern (a regexp or a string) or an array of patterns
234 *
235 * @return $this
236 *
237 * @see FilenameFilterIterator
238 */
239 public function path($patterns)
240 {
241 $this->paths = array_merge($this->paths, (array) $patterns);
242 return $this;
243 }
244 /**
245 * Adds rules that filenames must not match.
246 *
247 * You can use patterns (delimited with / sign) or simple strings.
248 *
249 * $finder->notPath('some/special/dir')
250 * $finder->notPath('/some\/special\/dir/') // same as above
251 * $finder->notPath(['some/file.txt', 'another/file.log'])
252 *
253 * Use only / as dirname separator.
254 *
255 * @param string|string[] $patterns A pattern (a regexp or a string) or an array of patterns
256 *
257 * @return $this
258 *
259 * @see FilenameFilterIterator
260 */
261 public function notPath($patterns)
262 {
263 $this->notPaths = array_merge($this->notPaths, (array) $patterns);
264 return $this;
265 }
266 /**
267 * Adds tests for file sizes.
268 *
269 * $finder->size('> 10K');
270 * $finder->size('<= 1Ki');
271 * $finder->size(4);
272 * $finder->size(['> 10K', '< 20K'])
273 *
274 * @param string|int|string[]|int[] $sizes A size range string or an integer or an array of size ranges
275 *
276 * @return $this
277 *
278 * @see SizeRangeFilterIterator
279 * @see NumberComparator
280 */
281 public function size($sizes)
282 {
283 foreach ((array) $sizes as $size) {
284 $this->sizes[] = new Comparator\NumberComparator($size);
285 }
286 return $this;
287 }
288 /**
289 * Excludes directories.
290 *
291 * Directories passed as argument must be relative to the ones defined with the `in()` method. For example:
292 *
293 * $finder->in(__DIR__)->exclude('ruby');
294 *
295 * @param string|array $dirs A directory path or an array of directories
296 *
297 * @return $this
298 *
299 * @see ExcludeDirectoryFilterIterator
300 */
301 public function exclude($dirs)
302 {
303 $this->exclude = array_merge($this->exclude, (array) $dirs);
304 return $this;
305 }
306 /**
307 * Excludes "hidden" directories and files (starting with a dot).
308 *
309 * This option is enabled by default.
310 *
311 * @return $this
312 *
313 * @see ExcludeDirectoryFilterIterator
314 */
315 public function ignoreDotFiles(bool $ignoreDotFiles)
316 {
317 if ($ignoreDotFiles) {
318 $this->ignore |= static::IGNORE_DOT_FILES;
319 } else {
320 $this->ignore &= ~static::IGNORE_DOT_FILES;
321 }
322 return $this;
323 }
324 /**
325 * Forces the finder to ignore version control directories.
326 *
327 * This option is enabled by default.
328 *
329 * @return $this
330 *
331 * @see ExcludeDirectoryFilterIterator
332 */
333 public function ignoreVCS(bool $ignoreVCS)
334 {
335 if ($ignoreVCS) {
336 $this->ignore |= static::IGNORE_VCS_FILES;
337 } else {
338 $this->ignore &= ~static::IGNORE_VCS_FILES;
339 }
340 return $this;
341 }
342 /**
343 * Forces Finder to obey .gitignore and ignore files based on rules listed there.
344 *
345 * This option is disabled by default.
346 *
347 * @return $this
348 */
349 public function ignoreVCSIgnored(bool $ignoreVCSIgnored)
350 {
351 if ($ignoreVCSIgnored) {
352 $this->ignore |= static::IGNORE_VCS_IGNORED_FILES;
353 } else {
354 $this->ignore &= ~static::IGNORE_VCS_IGNORED_FILES;
355 }
356 return $this;
357 }
358 /**
359 * Adds VCS patterns.
360 *
361 * @see ignoreVCS()
362 *
363 * @param string|string[] $pattern VCS patterns to ignore
364 */
365 public static function addVCSPattern($pattern)
366 {
367 foreach ((array) $pattern as $p) {
368 self::$vcsPatterns[] = $p;
369 }
370 self::$vcsPatterns = array_unique(self::$vcsPatterns);
371 }
372 /**
373 * Sorts files and directories by an anonymous function.
374 *
375 * The anonymous function receives two \SplFileInfo instances to compare.
376 *
377 * This can be slow as all the matching files and directories must be retrieved for comparison.
378 *
379 * @return $this
380 *
381 * @see SortableIterator
382 */
383 public function sort(\Closure $closure)
384 {
385 $this->sort = $closure;
386 return $this;
387 }
388 /**
389 * Sorts files and directories by name.
390 *
391 * This can be slow as all the matching files and directories must be retrieved for comparison.
392 *
393 * @return $this
394 *
395 * @see SortableIterator
396 */
397 public function sortByName(bool $useNaturalSort = \false)
398 {
399 $this->sort = $useNaturalSort ? Iterator\SortableIterator::SORT_BY_NAME_NATURAL : Iterator\SortableIterator::SORT_BY_NAME;
400 return $this;
401 }
402 /**
403 * Sorts files and directories by type (directories before files), then by name.
404 *
405 * This can be slow as all the matching files and directories must be retrieved for comparison.
406 *
407 * @return $this
408 *
409 * @see SortableIterator
410 */
411 public function sortByType()
412 {
413 $this->sort = Iterator\SortableIterator::SORT_BY_TYPE;
414 return $this;
415 }
416 /**
417 * Sorts files and directories by the last accessed time.
418 *
419 * This is the time that the file was last accessed, read or written to.
420 *
421 * This can be slow as all the matching files and directories must be retrieved for comparison.
422 *
423 * @return $this
424 *
425 * @see SortableIterator
426 */
427 public function sortByAccessedTime()
428 {
429 $this->sort = Iterator\SortableIterator::SORT_BY_ACCESSED_TIME;
430 return $this;
431 }
432 /**
433 * Reverses the sorting.
434 *
435 * @return $this
436 */
437 public function reverseSorting()
438 {
439 $this->reverseSorting = \true;
440 return $this;
441 }
442 /**
443 * Sorts files and directories by the last inode changed time.
444 *
445 * This is the time that the inode information was last modified (permissions, owner, group or other metadata).
446 *
447 * On Windows, since inode is not available, changed time is actually the file creation time.
448 *
449 * This can be slow as all the matching files and directories must be retrieved for comparison.
450 *
451 * @return $this
452 *
453 * @see SortableIterator
454 */
455 public function sortByChangedTime()
456 {
457 $this->sort = Iterator\SortableIterator::SORT_BY_CHANGED_TIME;
458 return $this;
459 }
460 /**
461 * Sorts files and directories by the last modified time.
462 *
463 * This is the last time the actual contents of the file were last modified.
464 *
465 * This can be slow as all the matching files and directories must be retrieved for comparison.
466 *
467 * @return $this
468 *
469 * @see SortableIterator
470 */
471 public function sortByModifiedTime()
472 {
473 $this->sort = Iterator\SortableIterator::SORT_BY_MODIFIED_TIME;
474 return $this;
475 }
476 /**
477 * Filters the iterator with an anonymous function.
478 *
479 * The anonymous function receives a \SplFileInfo and must return false
480 * to remove files.
481 *
482 * @return $this
483 *
484 * @see CustomFilterIterator
485 */
486 public function filter(\Closure $closure)
487 {
488 $this->filters[] = $closure;
489 return $this;
490 }
491 /**
492 * Forces the following of symlinks.
493 *
494 * @return $this
495 */
496 public function followLinks()
497 {
498 $this->followLinks = \true;
499 return $this;
500 }
501 /**
502 * Tells finder to ignore unreadable directories.
503 *
504 * By default, scanning unreadable directories content throws an AccessDeniedException.
505 *
506 * @return $this
507 */
508 public function ignoreUnreadableDirs(bool $ignore = \true)
509 {
510 $this->ignoreUnreadableDirs = $ignore;
511 return $this;
512 }
513 /**
514 * Searches files and directories which match defined rules.
515 *
516 * @param string|string[] $dirs A directory path or an array of directories
517 *
518 * @return $this
519 *
520 * @throws DirectoryNotFoundException if one of the directories does not exist
521 */
522 public function in($dirs)
523 {
524 $resolvedDirs = [];
525 foreach ((array) $dirs as $dir) {
526 if (is_dir($dir)) {
527 $resolvedDirs[] = [$this->normalizeDir($dir)];
528 } elseif ($glob = glob($dir, (\defined('GLOB_BRACE') ? \GLOB_BRACE : 0) | \GLOB_ONLYDIR | \GLOB_NOSORT)) {
529 sort($glob);
530 $resolvedDirs[] = array_map([$this, 'normalizeDir'], $glob);
531 } else {
532 throw new DirectoryNotFoundException(sprintf('The "%s" directory does not exist.', $dir));
533 }
534 }
535 $this->dirs = array_merge($this->dirs, ...$resolvedDirs);
536 return $this;
537 }
538 /**
539 * Returns an Iterator for the current Finder configuration.
540 *
541 * This method implements the IteratorAggregate interface.
542 *
543 * @return \Iterator<string, SplFileInfo>
544 *
545 * @throws \LogicException if the in() method has not been called
546 */
547 #[\ReturnTypeWillChange]
548 public function getIterator()
549 {
550 if (0 === \count($this->dirs) && 0 === \count($this->iterators)) {
551 throw new \LogicException('You must call one of in() or append() methods before iterating over a Finder.');
552 }
553 if (1 === \count($this->dirs) && 0 === \count($this->iterators)) {
554 $iterator = $this->searchInDirectory($this->dirs[0]);
555 if ($this->sort || $this->reverseSorting) {
556 $iterator = (new Iterator\SortableIterator($iterator, $this->sort, $this->reverseSorting))->getIterator();
557 }
558 return $iterator;
559 }
560 $iterator = new \AppendIterator();
561 foreach ($this->dirs as $dir) {
562 $iterator->append(new \IteratorIterator(new LazyIterator(function () use ($dir) {
563 return $this->searchInDirectory($dir);
564 })));
565 }
566 foreach ($this->iterators as $it) {
567 $iterator->append($it);
568 }
569 if ($this->sort || $this->reverseSorting) {
570 $iterator = (new Iterator\SortableIterator($iterator, $this->sort, $this->reverseSorting))->getIterator();
571 }
572 return $iterator;
573 }
574 /**
575 * Appends an existing set of files/directories to the finder.
576 *
577 * The set can be another Finder, an Iterator, an IteratorAggregate, or even a plain array.
578 *
579 * @return $this
580 *
581 * @throws \InvalidArgumentException when the given argument is not iterable
582 */
583 public function append(iterable $iterator)
584 {
585 if ($iterator instanceof \IteratorAggregate) {
586 $this->iterators[] = $iterator->getIterator();
587 } elseif ($iterator instanceof \Iterator) {
588 $this->iterators[] = $iterator;
589 } elseif (is_iterable($iterator)) {
590 $it = new \ArrayIterator();
591 foreach ($iterator as $file) {
592 $file = ($file instanceof \SplFileInfo) ? $file : new \SplFileInfo($file);
593 $it[$file->getPathname()] = $file;
594 }
595 $this->iterators[] = $it;
596 } else {
597 throw new \InvalidArgumentException('Finder::append() method wrong argument type.');
598 }
599 return $this;
600 }
601 /**
602 * Check if any results were found.
603 *
604 * @return bool
605 */
606 public function hasResults()
607 {
608 foreach ($this->getIterator() as $_) {
609 return \true;
610 }
611 return \false;
612 }
613 /**
614 * Counts all the results collected by the iterators.
615 *
616 * @return int
617 */
618 #[\ReturnTypeWillChange]
619 public function count()
620 {
621 return iterator_count($this->getIterator());
622 }
623 private function searchInDirectory(string $dir): \Iterator
624 {
625 $exclude = $this->exclude;
626 $notPaths = $this->notPaths;
627 if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) {
628 $exclude = array_merge($exclude, self::$vcsPatterns);
629 }
630 if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) {
631 $notPaths[] = '#(^|/)\..+(/|$)#';
632 }
633 $minDepth = 0;
634 $maxDepth = \PHP_INT_MAX;
635 foreach ($this->depths as $comparator) {
636 switch ($comparator->getOperator()) {
637 case '>':
638 $minDepth = $comparator->getTarget() + 1;
639 break;
640 case '>=':
641 $minDepth = $comparator->getTarget();
642 break;
643 case '<':
644 $maxDepth = $comparator->getTarget() - 1;
645 break;
646 case '<=':
647 $maxDepth = $comparator->getTarget();
648 break;
649 default:
650 $minDepth = $maxDepth = $comparator->getTarget();
651 }
652 }
653 $flags = \RecursiveDirectoryIterator::SKIP_DOTS;
654 if ($this->followLinks) {
655 $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
656 }
657 $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs);
658 if ($exclude) {
659 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $exclude);
660 }
661 $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
662 if ($minDepth > 0 || $maxDepth < \PHP_INT_MAX) {
663 $iterator = new Iterator\DepthRangeFilterIterator($iterator, $minDepth, $maxDepth);
664 }
665 if ($this->mode) {
666 $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode);
667 }
668 if ($this->names || $this->notNames) {
669 $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames);
670 }
671 if ($this->contains || $this->notContains) {
672 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
673 }
674 if ($this->sizes) {
675 $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes);
676 }
677 if ($this->dates) {
678 $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates);
679 }
680 if ($this->filters) {
681 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
682 }
683 if ($this->paths || $notPaths) {
684 $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $notPaths);
685 }
686 if (static::IGNORE_VCS_IGNORED_FILES === (static::IGNORE_VCS_IGNORED_FILES & $this->ignore)) {
687 $iterator = new Iterator\VcsIgnoredFilterIterator($iterator, $dir);
688 }
689 return $iterator;
690 }
691 /**
692 * Normalizes given directory names by removing trailing slashes.
693 *
694 * Excluding: (s)ftp:// or ssh2.(s)ftp:// wrapper
695 */
696 private function normalizeDir(string $dir): string
697 {
698 if ('/' === $dir) {
699 return $dir;
700 }
701 $dir = rtrim($dir, '/' . \DIRECTORY_SEPARATOR);
702 if (preg_match('#^(ssh2\.)?s?ftp://#', $dir)) {
703 $dir .= '/';
704 }
705 return $dir;
706 }
707 }
708