summaryrefslogtreecommitdiff
path: root/vendor/symfony
diff options
context:
space:
mode:
authorFrédéric Guillot <fred@kanboard.net>2017-12-15 13:27:25 -0800
committerFrédéric Guillot <fred@kanboard.net>2017-12-15 13:27:25 -0800
commit8e6476b4028e44687e10bf7fb2617a2d2fff97d2 (patch)
treef010db02cb0ff016bdc806a0a87e1a4b21946f0a /vendor/symfony
parenta93b8e10f5954be0853eec693c13e84c4bd9e6f2 (diff)
Update composer dependencies
Diffstat (limited to 'vendor/symfony')
-rw-r--r--vendor/symfony/finder/.gitignore3
-rw-r--r--vendor/symfony/finder/CHANGELOG.md55
-rw-r--r--vendor/symfony/finder/Comparator/Comparator.php98
-rw-r--r--vendor/symfony/finder/Comparator/DateComparator.php51
-rw-r--r--vendor/symfony/finder/Comparator/NumberComparator.php79
-rw-r--r--vendor/symfony/finder/Exception/AccessDeniedException.php19
-rw-r--r--vendor/symfony/finder/Exception/ExceptionInterface.php25
-rw-r--r--vendor/symfony/finder/Finder.php723
-rw-r--r--vendor/symfony/finder/Glob.php116
-rw-r--r--vendor/symfony/finder/Iterator/CustomFilterIterator.php61
-rw-r--r--vendor/symfony/finder/Iterator/DateRangeFilterIterator.php58
-rw-r--r--vendor/symfony/finder/Iterator/DepthRangeFilterIterator.php45
-rw-r--r--vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php84
-rw-r--r--vendor/symfony/finder/Iterator/FileTypeFilterIterator.php53
-rw-r--r--vendor/symfony/finder/Iterator/FilecontentFilterIterator.php58
-rw-r--r--vendor/symfony/finder/Iterator/FilenameFilterIterator.php47
-rw-r--r--vendor/symfony/finder/Iterator/FilterIterator.php60
-rw-r--r--vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php112
-rw-r--r--vendor/symfony/finder/Iterator/PathFilterIterator.php56
-rw-r--r--vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php154
-rw-r--r--vendor/symfony/finder/Iterator/SizeRangeFilterIterator.php57
-rw-r--r--vendor/symfony/finder/Iterator/SortableIterator.php80
-rw-r--r--vendor/symfony/finder/LICENSE19
-rw-r--r--vendor/symfony/finder/README.md14
-rw-r--r--vendor/symfony/finder/SplFileInfo.php79
-rw-r--r--vendor/symfony/finder/Tests/Comparator/ComparatorTest.php65
-rw-r--r--vendor/symfony/finder/Tests/Comparator/DateComparatorTest.php64
-rw-r--r--vendor/symfony/finder/Tests/Comparator/NumberComparatorTest.php108
-rw-r--r--vendor/symfony/finder/Tests/FinderTest.php698
-rw-r--r--vendor/symfony/finder/Tests/Fixtures/.dot/a0
-rw-r--r--vendor/symfony/finder/Tests/Fixtures/.dot/b/c.neon0
-rw-r--r--vendor/symfony/finder/Tests/Fixtures/.dot/b/d.neon0
-rw-r--r--vendor/symfony/finder/Tests/Fixtures/A/B/C/abc.dat0
-rw-r--r--vendor/symfony/finder/Tests/Fixtures/A/B/ab.dat0
-rw-r--r--vendor/symfony/finder/Tests/Fixtures/A/a.dat0
-rw-r--r--vendor/symfony/finder/Tests/Fixtures/copy/A/B/C/abc.dat.copy0
-rw-r--r--vendor/symfony/finder/Tests/Fixtures/copy/A/B/ab.dat.copy0
-rw-r--r--vendor/symfony/finder/Tests/Fixtures/copy/A/a.dat.copy0
-rw-r--r--vendor/symfony/finder/Tests/Fixtures/dolor.txt2
-rw-r--r--vendor/symfony/finder/Tests/Fixtures/ipsum.txt2
-rw-r--r--vendor/symfony/finder/Tests/Fixtures/lorem.txt2
-rw-r--r--vendor/symfony/finder/Tests/Fixtures/one/.dot1
-rw-r--r--vendor/symfony/finder/Tests/Fixtures/one/a0
-rw-r--r--vendor/symfony/finder/Tests/Fixtures/one/b/c.neon0
-rw-r--r--vendor/symfony/finder/Tests/Fixtures/one/b/d.neon0
-rw-r--r--vendor/symfony/finder/Tests/Fixtures/r+e.gex[c]a(r)s/dir/bar.dat0
-rw-r--r--vendor/symfony/finder/Tests/Fixtures/with space/foo.txt0
-rw-r--r--vendor/symfony/finder/Tests/GlobTest.php95
-rw-r--r--vendor/symfony/finder/Tests/Iterator/CustomFilterIteratorTest.php46
-rw-r--r--vendor/symfony/finder/Tests/Iterator/DateRangeFilterIteratorTest.php74
-rw-r--r--vendor/symfony/finder/Tests/Iterator/DepthRangeFilterIteratorTest.php83
-rw-r--r--vendor/symfony/finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.php80
-rw-r--r--vendor/symfony/finder/Tests/Iterator/FileTypeFilterIteratorTest.php73
-rw-r--r--vendor/symfony/finder/Tests/Iterator/FilecontentFilterIteratorTest.php86
-rw-r--r--vendor/symfony/finder/Tests/Iterator/FilenameFilterIteratorTest.php54
-rw-r--r--vendor/symfony/finder/Tests/Iterator/FilterIteratorTest.php53
-rw-r--r--vendor/symfony/finder/Tests/Iterator/Iterator.php55
-rw-r--r--vendor/symfony/finder/Tests/Iterator/IteratorTestCase.php100
-rw-r--r--vendor/symfony/finder/Tests/Iterator/MockFileListIterator.php21
-rw-r--r--vendor/symfony/finder/Tests/Iterator/MockSplFileInfo.php132
-rw-r--r--vendor/symfony/finder/Tests/Iterator/MultiplePcreFilterIteratorTest.php71
-rw-r--r--vendor/symfony/finder/Tests/Iterator/PathFilterIteratorTest.php82
-rw-r--r--vendor/symfony/finder/Tests/Iterator/RealIteratorTestCase.php110
-rw-r--r--vendor/symfony/finder/Tests/Iterator/RecursiveDirectoryIteratorTest.php59
-rw-r--r--vendor/symfony/finder/Tests/Iterator/SizeRangeFilterIteratorTest.php69
-rw-r--r--vendor/symfony/finder/Tests/Iterator/SortableIteratorTest.php183
-rw-r--r--vendor/symfony/finder/composer.json33
-rw-r--r--vendor/symfony/finder/phpunit.xml.dist30
68 files changed, 4737 insertions, 0 deletions
diff --git a/vendor/symfony/finder/.gitignore b/vendor/symfony/finder/.gitignore
new file mode 100644
index 00000000..c49a5d8d
--- /dev/null
+++ b/vendor/symfony/finder/.gitignore
@@ -0,0 +1,3 @@
+vendor/
+composer.lock
+phpunit.xml
diff --git a/vendor/symfony/finder/CHANGELOG.md b/vendor/symfony/finder/CHANGELOG.md
new file mode 100644
index 00000000..53c34be8
--- /dev/null
+++ b/vendor/symfony/finder/CHANGELOG.md
@@ -0,0 +1,55 @@
+CHANGELOG
+=========
+
+3.4.0
+-----
+
+ * deprecated `Symfony\Component\Finder\Iterator\FilterIterator`
+ * added Finder::hasResults() method to check if any results were found
+
+3.3.0
+-----
+
+ * added double-star matching to Glob::toRegex()
+
+3.0.0
+-----
+
+ * removed deprecated classes
+
+2.8.0
+-----
+
+ * deprecated adapters and related classes
+
+2.5.0
+-----
+ * added support for GLOB_BRACE in the paths passed to Finder::in()
+
+2.3.0
+-----
+
+ * added a way to ignore unreadable directories (via Finder::ignoreUnreadableDirs())
+ * unified the way subfolders that are not executable are handled by always throwing an AccessDeniedException exception
+
+2.2.0
+-----
+
+ * added Finder::path() and Finder::notPath() methods
+ * added finder adapters to improve performance on specific platforms
+ * added support for wildcard characters (glob patterns) in the paths passed
+ to Finder::in()
+
+2.1.0
+-----
+
+ * added Finder::sortByAccessedTime(), Finder::sortByChangedTime(), and
+ Finder::sortByModifiedTime()
+ * added Countable to Finder
+ * added support for an array of directories as an argument to
+ Finder::exclude()
+ * added searching based on the file content via Finder::contains() and
+ Finder::notContains()
+ * added support for the != operator in the Comparator
+ * [BC BREAK] filter expressions (used for file name and content) are no more
+ considered as regexps but glob patterns when they are enclosed in '*' or '?'
diff --git a/vendor/symfony/finder/Comparator/Comparator.php b/vendor/symfony/finder/Comparator/Comparator.php
new file mode 100644
index 00000000..4f5e1ffe
--- /dev/null
+++ b/vendor/symfony/finder/Comparator/Comparator.php
@@ -0,0 +1,98 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Comparator;
+
+/**
+ * Comparator.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class Comparator
+{
+ private $target;
+ private $operator = '==';
+
+ /**
+ * Gets the target value.
+ *
+ * @return string The target value
+ */
+ public function getTarget()
+ {
+ return $this->target;
+ }
+
+ /**
+ * Sets the target value.
+ *
+ * @param string $target The target value
+ */
+ public function setTarget($target)
+ {
+ $this->target = $target;
+ }
+
+ /**
+ * Gets the comparison operator.
+ *
+ * @return string The operator
+ */
+ public function getOperator()
+ {
+ return $this->operator;
+ }
+
+ /**
+ * Sets the comparison operator.
+ *
+ * @param string $operator A valid operator
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function setOperator($operator)
+ {
+ if (!$operator) {
+ $operator = '==';
+ }
+
+ if (!in_array($operator, array('>', '<', '>=', '<=', '==', '!='))) {
+ throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator));
+ }
+
+ $this->operator = $operator;
+ }
+
+ /**
+ * Tests against the target.
+ *
+ * @param mixed $test A test value
+ *
+ * @return bool
+ */
+ public function test($test)
+ {
+ switch ($this->operator) {
+ case '>':
+ return $test > $this->target;
+ case '>=':
+ return $test >= $this->target;
+ case '<':
+ return $test < $this->target;
+ case '<=':
+ return $test <= $this->target;
+ case '!=':
+ return $test != $this->target;
+ }
+
+ return $test == $this->target;
+ }
+}
diff --git a/vendor/symfony/finder/Comparator/DateComparator.php b/vendor/symfony/finder/Comparator/DateComparator.php
new file mode 100644
index 00000000..3de43ef4
--- /dev/null
+++ b/vendor/symfony/finder/Comparator/DateComparator.php
@@ -0,0 +1,51 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Comparator;
+
+/**
+ * DateCompare compiles date comparisons.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class DateComparator extends Comparator
+{
+ /**
+ * @param string $test A comparison string
+ *
+ * @throws \InvalidArgumentException If the test is not understood
+ */
+ public function __construct($test)
+ {
+ if (!preg_match('#^\s*(==|!=|[<>]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) {
+ throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a date test.', $test));
+ }
+
+ try {
+ $date = new \DateTime($matches[2]);
+ $target = $date->format('U');
+ } catch (\Exception $e) {
+ throw new \InvalidArgumentException(sprintf('"%s" is not a valid date.', $matches[2]));
+ }
+
+ $operator = isset($matches[1]) ? $matches[1] : '==';
+ if ('since' === $operator || 'after' === $operator) {
+ $operator = '>';
+ }
+
+ if ('until' === $operator || 'before' === $operator) {
+ $operator = '<';
+ }
+
+ $this->setOperator($operator);
+ $this->setTarget($target);
+ }
+}
diff --git a/vendor/symfony/finder/Comparator/NumberComparator.php b/vendor/symfony/finder/Comparator/NumberComparator.php
new file mode 100644
index 00000000..f62c0e57
--- /dev/null
+++ b/vendor/symfony/finder/Comparator/NumberComparator.php
@@ -0,0 +1,79 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Comparator;
+
+/**
+ * NumberComparator compiles a simple comparison to an anonymous
+ * subroutine, which you can call with a value to be tested again.
+ *
+ * Now this would be very pointless, if NumberCompare didn't understand
+ * magnitudes.
+ *
+ * The target value may use magnitudes of kilobytes (k, ki),
+ * megabytes (m, mi), or gigabytes (g, gi). Those suffixed
+ * with an i use the appropriate 2**n version in accordance with the
+ * IEC standard: http://physics.nist.gov/cuu/Units/binary.html
+ *
+ * Based on the Perl Number::Compare module.
+ *
+ * @author Fabien Potencier <fabien@symfony.com> PHP port
+ * @author Richard Clamp <richardc@unixbeard.net> Perl version
+ * @copyright 2004-2005 Fabien Potencier <fabien@symfony.com>
+ * @copyright 2002 Richard Clamp <richardc@unixbeard.net>
+ *
+ * @see http://physics.nist.gov/cuu/Units/binary.html
+ */
+class NumberComparator extends Comparator
+{
+ /**
+ * @param string|int $test A comparison string or an integer
+ *
+ * @throws \InvalidArgumentException If the test is not understood
+ */
+ public function __construct($test)
+ {
+ if (!preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) {
+ throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test));
+ }
+
+ $target = $matches[2];
+ if (!is_numeric($target)) {
+ throw new \InvalidArgumentException(sprintf('Invalid number "%s".', $target));
+ }
+ if (isset($matches[3])) {
+ // magnitude
+ switch (strtolower($matches[3])) {
+ case 'k':
+ $target *= 1000;
+ break;
+ case 'ki':
+ $target *= 1024;
+ break;
+ case 'm':
+ $target *= 1000000;
+ break;
+ case 'mi':
+ $target *= 1024 * 1024;
+ break;
+ case 'g':
+ $target *= 1000000000;
+ break;
+ case 'gi':
+ $target *= 1024 * 1024 * 1024;
+ break;
+ }
+ }
+
+ $this->setTarget($target);
+ $this->setOperator(isset($matches[1]) ? $matches[1] : '==');
+ }
+}
diff --git a/vendor/symfony/finder/Exception/AccessDeniedException.php b/vendor/symfony/finder/Exception/AccessDeniedException.php
new file mode 100644
index 00000000..ee195ea8
--- /dev/null
+++ b/vendor/symfony/finder/Exception/AccessDeniedException.php
@@ -0,0 +1,19 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Exception;
+
+/**
+ * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
+ */
+class AccessDeniedException extends \UnexpectedValueException
+{
+}
diff --git a/vendor/symfony/finder/Exception/ExceptionInterface.php b/vendor/symfony/finder/Exception/ExceptionInterface.php
new file mode 100644
index 00000000..161e9686
--- /dev/null
+++ b/vendor/symfony/finder/Exception/ExceptionInterface.php
@@ -0,0 +1,25 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Exception;
+
+/**
+ * @author Jean-François Simon <contact@jfsimon.fr>
+ *
+ * @deprecated since 3.3, to be removed in 4.0.
+ */
+interface ExceptionInterface
+{
+ /**
+ * @return \Symfony\Component\Finder\Adapter\AdapterInterface
+ */
+ public function getAdapter();
+}
diff --git a/vendor/symfony/finder/Finder.php b/vendor/symfony/finder/Finder.php
new file mode 100644
index 00000000..07dce771
--- /dev/null
+++ b/vendor/symfony/finder/Finder.php
@@ -0,0 +1,723 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder;
+
+use Symfony\Component\Finder\Comparator\DateComparator;
+use Symfony\Component\Finder\Comparator\NumberComparator;
+use Symfony\Component\Finder\Iterator\CustomFilterIterator;
+use Symfony\Component\Finder\Iterator\DateRangeFilterIterator;
+use Symfony\Component\Finder\Iterator\DepthRangeFilterIterator;
+use Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator;
+use Symfony\Component\Finder\Iterator\FilecontentFilterIterator;
+use Symfony\Component\Finder\Iterator\FilenameFilterIterator;
+use Symfony\Component\Finder\Iterator\SizeRangeFilterIterator;
+use Symfony\Component\Finder\Iterator\SortableIterator;
+
+/**
+ * Finder allows to build rules to find files and directories.
+ *
+ * It is a thin wrapper around several specialized iterator classes.
+ *
+ * All rules may be invoked several times.
+ *
+ * All methods return the current Finder object to allow easy chaining:
+ *
+ * $finder = Finder::create()->files()->name('*.php')->in(__DIR__);
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class Finder implements \IteratorAggregate, \Countable
+{
+ const IGNORE_VCS_FILES = 1;
+ const IGNORE_DOT_FILES = 2;
+
+ private $mode = 0;
+ private $names = array();
+ private $notNames = array();
+ private $exclude = array();
+ private $filters = array();
+ private $depths = array();
+ private $sizes = array();
+ private $followLinks = false;
+ private $sort = false;
+ private $ignore = 0;
+ private $dirs = array();
+ private $dates = array();
+ private $iterators = array();
+ private $contains = array();
+ private $notContains = array();
+ private $paths = array();
+ private $notPaths = array();
+ private $ignoreUnreadableDirs = false;
+
+ private static $vcsPatterns = array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg');
+
+ public function __construct()
+ {
+ $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES;
+ }
+
+ /**
+ * Creates a new Finder.
+ *
+ * @return static
+ */
+ public static function create()
+ {
+ return new static();
+ }
+
+ /**
+ * Restricts the matching to directories only.
+ *
+ * @return $this
+ */
+ public function directories()
+ {
+ $this->mode = Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES;
+
+ return $this;
+ }
+
+ /**
+ * Restricts the matching to files only.
+ *
+ * @return $this
+ */
+ public function files()
+ {
+ $this->mode = Iterator\FileTypeFilterIterator::ONLY_FILES;
+
+ return $this;
+ }
+
+ /**
+ * Adds tests for the directory depth.
+ *
+ * Usage:
+ *
+ * $finder->depth('> 1') // the Finder will start matching at level 1.
+ * $finder->depth('< 3') // the Finder will descend at most 3 levels of directories below the starting point.
+ *
+ * @param string|int $level The depth level expression
+ *
+ * @return $this
+ *
+ * @see DepthRangeFilterIterator
+ * @see NumberComparator
+ */
+ public function depth($level)
+ {
+ $this->depths[] = new Comparator\NumberComparator($level);
+
+ return $this;
+ }
+
+ /**
+ * Adds tests for file dates (last modified).
+ *
+ * The date must be something that strtotime() is able to parse:
+ *
+ * $finder->date('since yesterday');
+ * $finder->date('until 2 days ago');
+ * $finder->date('> now - 2 hours');
+ * $finder->date('>= 2005-10-15');
+ *
+ * @param string $date A date range string
+ *
+ * @return $this
+ *
+ * @see strtotime
+ * @see DateRangeFilterIterator
+ * @see DateComparator
+ */
+ public function date($date)
+ {
+ $this->dates[] = new Comparator\DateComparator($date);
+
+ return $this;
+ }
+
+ /**
+ * Adds rules that files must match.
+ *
+ * You can use patterns (delimited with / sign), globs or simple strings.
+ *
+ * $finder->name('*.php')
+ * $finder->name('/\.php$/') // same as above
+ * $finder->name('test.php')
+ *
+ * @param string $pattern A pattern (a regexp, a glob, or a string)
+ *
+ * @return $this
+ *
+ * @see FilenameFilterIterator
+ */
+ public function name($pattern)
+ {
+ $this->names[] = $pattern;
+
+ return $this;
+ }
+
+ /**
+ * Adds rules that files must not match.
+ *
+ * @param string $pattern A pattern (a regexp, a glob, or a string)
+ *
+ * @return $this
+ *
+ * @see FilenameFilterIterator
+ */
+ public function notName($pattern)
+ {
+ $this->notNames[] = $pattern;
+
+ return $this;
+ }
+
+ /**
+ * Adds tests that file contents must match.
+ *
+ * Strings or PCRE patterns can be used:
+ *
+ * $finder->contains('Lorem ipsum')
+ * $finder->contains('/Lorem ipsum/i')
+ *
+ * @param string $pattern A pattern (string or regexp)
+ *
+ * @return $this
+ *
+ * @see FilecontentFilterIterator
+ */
+ public function contains($pattern)
+ {
+ $this->contains[] = $pattern;
+
+ return $this;
+ }
+
+ /**
+ * Adds tests that file contents must not match.
+ *
+ * Strings or PCRE patterns can be used:
+ *
+ * $finder->notContains('Lorem ipsum')
+ * $finder->notContains('/Lorem ipsum/i')
+ *
+ * @param string $pattern A pattern (string or regexp)
+ *
+ * @return $this
+ *
+ * @see FilecontentFilterIterator
+ */
+ public function notContains($pattern)
+ {
+ $this->notContains[] = $pattern;
+
+ return $this;
+ }
+
+ /**
+ * Adds rules that filenames must match.
+ *
+ * You can use patterns (delimited with / sign) or simple strings.
+ *
+ * $finder->path('some/special/dir')
+ * $finder->path('/some\/special\/dir/') // same as above
+ *
+ * Use only / as dirname separator.
+ *
+ * @param string $pattern A pattern (a regexp or a string)
+ *
+ * @return $this
+ *
+ * @see FilenameFilterIterator
+ */
+ public function path($pattern)
+ {
+ $this->paths[] = $pattern;
+
+ return $this;
+ }
+
+ /**
+ * Adds rules that filenames must not match.
+ *
+ * You can use patterns (delimited with / sign) or simple strings.
+ *
+ * $finder->notPath('some/special/dir')
+ * $finder->notPath('/some\/special\/dir/') // same as above
+ *
+ * Use only / as dirname separator.
+ *
+ * @param string $pattern A pattern (a regexp or a string)
+ *
+ * @return $this
+ *
+ * @see FilenameFilterIterator
+ */
+ public function notPath($pattern)
+ {
+ $this->notPaths[] = $pattern;
+
+ return $this;
+ }
+
+ /**
+ * Adds tests for file sizes.
+ *
+ * $finder->size('> 10K');
+ * $finder->size('<= 1Ki');
+ * $finder->size(4);
+ *
+ * @param string|int $size A size range string or an integer
+ *
+ * @return $this
+ *
+ * @see SizeRangeFilterIterator
+ * @see NumberComparator
+ */
+ public function size($size)
+ {
+ $this->sizes[] = new Comparator\NumberComparator($size);
+
+ return $this;
+ }
+
+ /**
+ * Excludes directories.
+ *
+ * @param string|array $dirs A directory path or an array of directories
+ *
+ * @return $this
+ *
+ * @see ExcludeDirectoryFilterIterator
+ */
+ public function exclude($dirs)
+ {
+ $this->exclude = array_merge($this->exclude, (array) $dirs);
+
+ return $this;
+ }
+
+ /**
+ * Excludes "hidden" directories and files (starting with a dot).
+ *
+ * @param bool $ignoreDotFiles Whether to exclude "hidden" files or not
+ *
+ * @return $this
+ *
+ * @see ExcludeDirectoryFilterIterator
+ */
+ public function ignoreDotFiles($ignoreDotFiles)
+ {
+ if ($ignoreDotFiles) {
+ $this->ignore |= static::IGNORE_DOT_FILES;
+ } else {
+ $this->ignore &= ~static::IGNORE_DOT_FILES;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Forces the finder to ignore version control directories.
+ *
+ * @param bool $ignoreVCS Whether to exclude VCS files or not
+ *
+ * @return $this
+ *
+ * @see ExcludeDirectoryFilterIterator
+ */
+ public function ignoreVCS($ignoreVCS)
+ {
+ if ($ignoreVCS) {
+ $this->ignore |= static::IGNORE_VCS_FILES;
+ } else {
+ $this->ignore &= ~static::IGNORE_VCS_FILES;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Adds VCS patterns.
+ *
+ * @see ignoreVCS()
+ *
+ * @param string|string[] $pattern VCS patterns to ignore
+ */
+ public static function addVCSPattern($pattern)
+ {
+ foreach ((array) $pattern as $p) {
+ self::$vcsPatterns[] = $p;
+ }
+
+ self::$vcsPatterns = array_unique(self::$vcsPatterns);
+ }
+
+ /**
+ * Sorts files and directories by an anonymous function.
+ *
+ * The anonymous function receives two \SplFileInfo instances to compare.
+ *
+ * This can be slow as all the matching files and directories must be retrieved for comparison.
+ *
+ * @return $this
+ *
+ * @see SortableIterator
+ */
+ public function sort(\Closure $closure)
+ {
+ $this->sort = $closure;
+
+ return $this;
+ }
+
+ /**
+ * Sorts files and directories by name.
+ *
+ * This can be slow as all the matching files and directories must be retrieved for comparison.
+ *
+ * @return $this
+ *
+ * @see SortableIterator
+ */
+ public function sortByName()
+ {
+ $this->sort = Iterator\SortableIterator::SORT_BY_NAME;
+
+ return $this;
+ }
+
+ /**
+ * Sorts files and directories by type (directories before files), then by name.
+ *
+ * This can be slow as all the matching files and directories must be retrieved for comparison.
+ *
+ * @return $this
+ *
+ * @see SortableIterator
+ */
+ public function sortByType()
+ {
+ $this->sort = Iterator\SortableIterator::SORT_BY_TYPE;
+
+ return $this;
+ }
+
+ /**
+ * Sorts files and directories by the last accessed time.
+ *
+ * This is the time that the file was last accessed, read or written to.
+ *
+ * This can be slow as all the matching files and directories must be retrieved for comparison.
+ *
+ * @return $this
+ *
+ * @see SortableIterator
+ */
+ public function sortByAccessedTime()
+ {
+ $this->sort = Iterator\SortableIterator::SORT_BY_ACCESSED_TIME;
+
+ return $this;
+ }
+
+ /**
+ * Sorts files and directories by the last inode changed time.
+ *
+ * This is the time that the inode information was last modified (permissions, owner, group or other metadata).
+ *
+ * On Windows, since inode is not available, changed time is actually the file creation time.
+ *
+ * This can be slow as all the matching files and directories must be retrieved for comparison.
+ *
+ * @return $this
+ *
+ * @see SortableIterator
+ */
+ public function sortByChangedTime()
+ {
+ $this->sort = Iterator\SortableIterator::SORT_BY_CHANGED_TIME;
+
+ return $this;
+ }
+
+ /**
+ * Sorts files and directories by the last modified time.
+ *
+ * This is the last time the actual contents of the file were last modified.
+ *
+ * This can be slow as all the matching files and directories must be retrieved for comparison.
+ *
+ * @return $this
+ *
+ * @see SortableIterator
+ */
+ public function sortByModifiedTime()
+ {
+ $this->sort = Iterator\SortableIterator::SORT_BY_MODIFIED_TIME;
+
+ return $this;
+ }
+
+ /**
+ * Filters the iterator with an anonymous function.
+ *
+ * The anonymous function receives a \SplFileInfo and must return false
+ * to remove files.
+ *
+ * @return $this
+ *
+ * @see CustomFilterIterator
+ */
+ public function filter(\Closure $closure)
+ {
+ $this->filters[] = $closure;
+
+ return $this;
+ }
+
+ /**
+ * Forces the following of symlinks.
+ *
+ * @return $this
+ */
+ public function followLinks()
+ {
+ $this->followLinks = true;
+
+ return $this;
+ }
+
+ /**
+ * Tells finder to ignore unreadable directories.
+ *
+ * By default, scanning unreadable directories content throws an AccessDeniedException.
+ *
+ * @param bool $ignore
+ *
+ * @return $this
+ */
+ public function ignoreUnreadableDirs($ignore = true)
+ {
+ $this->ignoreUnreadableDirs = (bool) $ignore;
+
+ return $this;
+ }
+
+ /**
+ * Searches files and directories which match defined rules.
+ *
+ * @param string|array $dirs A directory path or an array of directories
+ *
+ * @return $this
+ *
+ * @throws \InvalidArgumentException if one of the directories does not exist
+ */
+ public function in($dirs)
+ {
+ $resolvedDirs = array();
+
+ foreach ((array) $dirs as $dir) {
+ if (is_dir($dir)) {
+ $resolvedDirs[] = $dir;
+ } elseif ($glob = glob($dir, (defined('GLOB_BRACE') ? GLOB_BRACE : 0) | GLOB_ONLYDIR)) {
+ $resolvedDirs = array_merge($resolvedDirs, $glob);
+ } else {
+ throw new \InvalidArgumentException(sprintf('The "%s" directory does not exist.', $dir));
+ }
+ }
+
+ $this->dirs = array_merge($this->dirs, $resolvedDirs);
+
+ return $this;
+ }
+
+ /**
+ * Returns an Iterator for the current Finder configuration.
+ *
+ * This method implements the IteratorAggregate interface.
+ *
+ * @return \Iterator|SplFileInfo[] An iterator
+ *
+ * @throws \LogicException if the in() method has not been called
+ */
+ public function getIterator()
+ {
+ if (0 === count($this->dirs) && 0 === count($this->iterators)) {
+ throw new \LogicException('You must call one of in() or append() methods before iterating over a Finder.');
+ }
+
+ if (1 === count($this->dirs) && 0 === count($this->iterators)) {
+ return $this->searchInDirectory($this->dirs[0]);
+ }
+
+ $iterator = new \AppendIterator();
+ foreach ($this->dirs as $dir) {
+ $iterator->append($this->searchInDirectory($dir));
+ }
+
+ foreach ($this->iterators as $it) {
+ $iterator->append($it);
+ }
+
+ return $iterator;
+ }
+
+ /**
+ * Appends an existing set of files/directories to the finder.
+ *
+ * The set can be another Finder, an Iterator, an IteratorAggregate, or even a plain array.
+ *
+ * @param mixed $iterator
+ *
+ * @return $this
+ *
+ * @throws \InvalidArgumentException when the given argument is not iterable
+ */
+ public function append($iterator)
+ {
+ if ($iterator instanceof \IteratorAggregate) {
+ $this->iterators[] = $iterator->getIterator();
+ } elseif ($iterator instanceof \Iterator) {
+ $this->iterators[] = $iterator;
+ } elseif ($iterator instanceof \Traversable || is_array($iterator)) {
+ $it = new \ArrayIterator();
+ foreach ($iterator as $file) {
+ $it->append($file instanceof \SplFileInfo ? $file : new \SplFileInfo($file));
+ }
+ $this->iterators[] = $it;
+ } else {
+ throw new \InvalidArgumentException('Finder::append() method wrong argument type.');
+ }
+
+ return $this;
+ }
+
+ /**
+ * Check if the any results were found.
+ *
+ * @return bool
+ */
+ public function hasResults()
+ {
+ foreach ($this->getIterator() as $_) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Counts all the results collected by the iterators.
+ *
+ * @return int
+ */
+ public function count()
+ {
+ return iterator_count($this->getIterator());
+ }
+
+ /**
+ * @param $dir
+ *
+ * @return \Iterator
+ */
+ private function searchInDirectory($dir)
+ {
+ if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) {
+ $this->exclude = array_merge($this->exclude, self::$vcsPatterns);
+ }
+
+ if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) {
+ $this->notPaths[] = '#(^|/)\..+(/|$)#';
+ }
+
+ $minDepth = 0;
+ $maxDepth = PHP_INT_MAX;
+
+ foreach ($this->depths as $comparator) {
+ switch ($comparator->getOperator()) {
+ case '>':
+ $minDepth = $comparator->getTarget() + 1;
+ break;
+ case '>=':
+ $minDepth = $comparator->getTarget();
+ break;
+ case '<':
+ $maxDepth = $comparator->getTarget() - 1;
+ break;
+ case '<=':
+ $maxDepth = $comparator->getTarget();
+ break;
+ default:
+ $minDepth = $maxDepth = $comparator->getTarget();
+ }
+ }
+
+ $flags = \RecursiveDirectoryIterator::SKIP_DOTS;
+
+ if ($this->followLinks) {
+ $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
+ }
+
+ $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs);
+
+ if ($this->exclude) {
+ $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
+ }
+
+ $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
+
+ if ($minDepth > 0 || $maxDepth < PHP_INT_MAX) {
+ $iterator = new Iterator\DepthRangeFilterIterator($iterator, $minDepth, $maxDepth);
+ }
+
+ if ($this->mode) {
+ $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode);
+ }
+
+ if ($this->names || $this->notNames) {
+ $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames);
+ }
+
+ if ($this->contains || $this->notContains) {
+ $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
+ }
+
+ if ($this->sizes) {
+ $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes);
+ }
+
+ if ($this->dates) {
+ $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates);
+ }
+
+ if ($this->filters) {
+ $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
+ }
+
+ if ($this->paths || $this->notPaths) {
+ $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths);
+ }
+
+ if ($this->sort) {
+ $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
+ $iterator = $iteratorAggregate->getIterator();
+ }
+
+ return $iterator;
+ }
+}
diff --git a/vendor/symfony/finder/Glob.php b/vendor/symfony/finder/Glob.php
new file mode 100644
index 00000000..df8b86fa
--- /dev/null
+++ b/vendor/symfony/finder/Glob.php
@@ -0,0 +1,116 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder;
+
+/**
+ * Glob matches globbing patterns against text.
+ *
+ * if match_glob("foo.*", "foo.bar") echo "matched\n";
+ *
+ * // prints foo.bar and foo.baz
+ * $regex = glob_to_regex("foo.*");
+ * for (array('foo.bar', 'foo.baz', 'foo', 'bar') as $t)
+ * {
+ * if (/$regex/) echo "matched: $car\n";
+ * }
+ *
+ * Glob implements glob(3) style matching that can be used to match
+ * against text, rather than fetching names from a filesystem.
+ *
+ * Based on the Perl Text::Glob module.
+ *
+ * @author Fabien Potencier <fabien@symfony.com> PHP port
+ * @author Richard Clamp <richardc@unixbeard.net> Perl version
+ * @copyright 2004-2005 Fabien Potencier <fabien@symfony.com>
+ * @copyright 2002 Richard Clamp <richardc@unixbeard.net>
+ */
+class Glob
+{
+ /**
+ * Returns a regexp which is the equivalent of the glob pattern.
+ *
+ * @param string $glob The glob pattern
+ * @param bool $strictLeadingDot
+ * @param bool $strictWildcardSlash
+ * @param string $delimiter Optional delimiter
+ *
+ * @return string regex The regexp
+ */
+ public static function toRegex($glob, $strictLeadingDot = true, $strictWildcardSlash = true, $delimiter = '#')
+ {
+ $firstByte = true;
+ $escaping = false;
+ $inCurlies = 0;
+ $regex = '';
+ $sizeGlob = strlen($glob);
+ for ($i = 0; $i < $sizeGlob; ++$i) {
+ $car = $glob[$i];
+ if ($firstByte && $strictLeadingDot && '.' !== $car) {
+ $regex .= '(?=[^\.])';
+ }
+
+ $firstByte = '/' === $car;
+
+ if ($firstByte && $strictWildcardSlash && isset($glob[$i + 2]) && '**' === $glob[$i + 1].$glob[$i + 2] && (!isset($glob[$i + 3]) || '/' === $glob[$i + 3])) {
+ $car = '[^/]++/';
+ if (!isset($glob[$i + 3])) {
+ $car .= '?';
+ }
+
+ if ($strictLeadingDot) {
+ $car = '(?=[^\.])'.$car;
+ }
+
+ $car = '/(?:'.$car.')*';
+ $i += 2 + isset($glob[$i + 3]);
+
+ if ('/' === $delimiter) {
+ $car = str_replace('/', '\\/', $car);
+ }
+ }
+
+ if ($delimiter === $car || '.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) {
+ $regex .= "\\$car";
+ } elseif ('*' === $car) {
+ $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*');
+ } elseif ('?' === $car) {
+ $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.');
+ } elseif ('{' === $car) {
+ $regex .= $escaping ? '\\{' : '(';
+ if (!$escaping) {
+ ++$inCurlies;
+ }
+ } elseif ('}' === $car && $inCurlies) {
+ $regex .= $escaping ? '}' : ')';
+ if (!$escaping) {
+ --$inCurlies;
+ }
+ } elseif (',' === $car && $inCurlies) {
+ $regex .= $escaping ? ',' : '|';
+ } elseif ('\\' === $car) {
+ if ($escaping) {
+ $regex .= '\\\\';
+ $escaping = false;
+ } else {
+ $escaping = true;
+ }
+
+ continue;
+ } else {
+ $regex .= $car;
+ }
+ $escaping = false;
+ }
+
+ return $delimiter.'^'.$regex.'$'.$delimiter;
+ }
+}
diff --git a/vendor/symfony/finder/Iterator/CustomFilterIterator.php b/vendor/symfony/finder/Iterator/CustomFilterIterator.php
new file mode 100644
index 00000000..399b6a97
--- /dev/null
+++ b/vendor/symfony/finder/Iterator/CustomFilterIterator.php
@@ -0,0 +1,61 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Iterator;
+
+/**
+ * CustomFilterIterator filters files by applying anonymous functions.
+ *
+ * The anonymous function receives a \SplFileInfo and must return false
+ * to remove files.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class CustomFilterIterator extends FilterIterator
+{
+ private $filters = array();
+
+ /**
+ * @param \Iterator $iterator The Iterator to filter
+ * @param callable[] $filters An array of PHP callbacks
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function __construct(\Iterator $iterator, array $filters)
+ {
+ foreach ($filters as $filter) {
+ if (!is_callable($filter)) {
+ throw new \InvalidArgumentException('Invalid PHP callback.');
+ }
+ }
+ $this->filters = $filters;
+
+ parent::__construct($iterator);
+ }
+
+ /**
+ * Filters the iterator values.
+ *
+ * @return bool true if the value should be kept, false otherwise
+ */
+ public function accept()
+ {
+ $fileinfo = $this->current();
+
+ foreach ($this->filters as $filter) {
+ if (false === call_user_func($filter, $fileinfo)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/vendor/symfony/finder/Iterator/DateRangeFilterIterator.php b/vendor/symfony/finder/Iterator/DateRangeFilterIterator.php
new file mode 100644
index 00000000..b01e5e3f
--- /dev/null
+++ b/vendor/symfony/finder/Iterator/DateRangeFilterIterator.php
@@ -0,0 +1,58 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Iterator;
+
+use Symfony\Component\Finder\Comparator\DateComparator;
+
+/**
+ * DateRangeFilterIterator filters out files that are not in the given date range (last modified dates).
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class DateRangeFilterIterator extends FilterIterator
+{
+ private $comparators = array();
+
+ /**
+ * @param \Iterator $iterator The Iterator to filter
+ * @param DateComparator[] $comparators An array of DateComparator instances
+ */
+ public function __construct(\Iterator $iterator, array $comparators)
+ {
+ $this->comparators = $comparators;
+
+ parent::__construct($iterator);
+ }
+
+ /**
+ * Filters the iterator values.
+ *
+ * @return bool true if the value should be kept, false otherwise
+ */
+ public function accept()
+ {
+ $fileinfo = $this->current();
+
+ if (!file_exists($fileinfo->getPathname())) {
+ return false;
+ }
+
+ $filedate = $fileinfo->getMTime();
+ foreach ($this->comparators as $compare) {
+ if (!$compare->test($filedate)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/vendor/symfony/finder/Iterator/DepthRangeFilterIterator.php b/vendor/symfony/finder/Iterator/DepthRangeFilterIterator.php
new file mode 100644
index 00000000..ce9d3aa7
--- /dev/null
+++ b/vendor/symfony/finder/Iterator/DepthRangeFilterIterator.php
@@ -0,0 +1,45 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Iterator;
+
+/**
+ * DepthRangeFilterIterator limits the directory depth.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class DepthRangeFilterIterator extends FilterIterator
+{
+ private $minDepth = 0;
+
+ /**
+ * @param \RecursiveIteratorIterator $iterator The Iterator to filter
+ * @param int $minDepth The min depth
+ * @param int $maxDepth The max depth
+ */
+ public function __construct(\RecursiveIteratorIterator $iterator, $minDepth = 0, $maxDepth = PHP_INT_MAX)
+ {
+ $this->minDepth = $minDepth;
+ $iterator->setMaxDepth(PHP_INT_MAX === $maxDepth ? -1 : $maxDepth);
+
+ parent::__construct($iterator);
+ }
+
+ /**
+ * Filters the iterator values.
+ *
+ * @return bool true if the value should be kept, false otherwise
+ */
+ public function accept()
+ {
+ return $this->getInnerIterator()->getDepth() >= $this->minDepth;
+ }
+}
diff --git a/vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php b/vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php
new file mode 100644
index 00000000..c57128c2
--- /dev/null
+++ b/vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php
@@ -0,0 +1,84 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Iterator;
+
+/**
+ * ExcludeDirectoryFilterIterator filters out directories.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class ExcludeDirectoryFilterIterator extends FilterIterator implements \RecursiveIterator
+{
+ private $iterator;
+ private $isRecursive;
+ private $excludedDirs = array();
+ private $excludedPattern;
+
+ /**
+ * @param \Iterator $iterator The Iterator to filter
+ * @param array $directories An array of directories to exclude
+ */
+ public function __construct(\Iterator $iterator, array $directories)
+ {
+ $this->iterator = $iterator;
+ $this->isRecursive = $iterator instanceof \RecursiveIterator;
+ $patterns = array();
+ foreach ($directories as $directory) {
+ $directory = rtrim($directory, '/');
+ if (!$this->isRecursive || false !== strpos($directory, '/')) {
+ $patterns[] = preg_quote($directory, '#');
+ } else {
+ $this->excludedDirs[$directory] = true;
+ }
+ }
+ if ($patterns) {
+ $this->excludedPattern = '#(?:^|/)(?:'.implode('|', $patterns).')(?:/|$)#';
+ }
+
+ parent::__construct($iterator);
+ }
+
+ /**
+ * Filters the iterator values.
+ *
+ * @return bool True if the value should be kept, false otherwise
+ */
+ public function accept()
+ {
+ if ($this->isRecursive && isset($this->excludedDirs[$this->getFilename()]) && $this->isDir()) {
+ return false;
+ }
+
+ if ($this->excludedPattern) {
+ $path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath();
+ $path = str_replace('\\', '/', $path);
+
+ return !preg_match($this->excludedPattern, $path);
+ }
+
+ return true;
+ }
+
+ public function hasChildren()
+ {
+ return $this->isRecursive && $this->iterator->hasChildren();
+ }
+
+ public function getChildren()
+ {
+ $children = new self($this->iterator->getChildren(), array());
+ $children->excludedDirs = $this->excludedDirs;
+ $children->excludedPattern = $this->excludedPattern;
+
+ return $children;
+ }
+}
diff --git a/vendor/symfony/finder/Iterator/FileTypeFilterIterator.php b/vendor/symfony/finder/Iterator/FileTypeFilterIterator.php
new file mode 100644
index 00000000..e9811d4a
--- /dev/null
+++ b/vendor/symfony/finder/Iterator/FileTypeFilterIterator.php
@@ -0,0 +1,53 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Iterator;
+
+/**
+ * FileTypeFilterIterator only keeps files, directories, or both.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class FileTypeFilterIterator extends FilterIterator
+{
+ const ONLY_FILES = 1;
+ const ONLY_DIRECTORIES = 2;
+
+ private $mode;
+
+ /**
+ * @param \Iterator $iterator The Iterator to filter
+ * @param int $mode The mode (self::ONLY_FILES or self::ONLY_DIRECTORIES)
+ */
+ public function __construct(\Iterator $iterator, $mode)
+ {
+ $this->mode = $mode;
+
+ parent::__construct($iterator);
+ }
+
+ /**
+ * Filters the iterator values.
+ *
+ * @return bool true if the value should be kept, false otherwise
+ */
+ public function accept()
+ {
+ $fileinfo = $this->current();
+ if (self::ONLY_DIRECTORIES === (self::ONLY_DIRECTORIES & $this->mode) && $fileinfo->isFile()) {
+ return false;
+ } elseif (self::ONLY_FILES === (self::ONLY_FILES & $this->mode) && $fileinfo->isDir()) {
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/vendor/symfony/finder/Iterator/FilecontentFilterIterator.php b/vendor/symfony/finder/Iterator/FilecontentFilterIterator.php
new file mode 100644
index 00000000..81594b87
--- /dev/null
+++ b/vendor/symfony/finder/Iterator/FilecontentFilterIterator.php
@@ -0,0 +1,58 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Iterator;
+
+/**
+ * FilecontentFilterIterator filters files by their contents using patterns (regexps or strings).
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Włodzimierz Gajda <gajdaw@gajdaw.pl>
+ */
+class FilecontentFilterIterator extends MultiplePcreFilterIterator
+{
+ /**
+ * Filters the iterator values.
+ *
+ * @return bool true if the value should be kept, false otherwise
+ */
+ public function accept()
+ {
+ if (!$this->matchRegexps && !$this->noMatchRegexps) {
+ return true;
+ }
+
+ $fileinfo = $this->current();
+
+ if ($fileinfo->isDir() || !$fileinfo->isReadable()) {
+ return false;
+ }
+
+ $content = $fileinfo->getContents();
+ if (!$content) {
+ return false;
+ }
+
+ return $this->isAccepted($content);
+ }
+
+ /**
+ * Converts string to regexp if necessary.
+ *
+ * @param string $str Pattern: string or regexp
+ *
+ * @return string regexp corresponding to a given string or regexp
+ */
+ protected function toRegex($str)
+ {
+ return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
+ }
+}
diff --git a/vendor/symfony/finder/Iterator/FilenameFilterIterator.php b/vendor/symfony/finder/Iterator/FilenameFilterIterator.php
new file mode 100644
index 00000000..e168cd8f
--- /dev/null
+++ b/vendor/symfony/finder/Iterator/FilenameFilterIterator.php
@@ -0,0 +1,47 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Iterator;
+
+use Symfony\Component\Finder\Glob;
+
+/**
+ * FilenameFilterIterator filters files by patterns (a regexp, a glob, or a string).
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class FilenameFilterIterator extends MultiplePcreFilterIterator
+{
+ /**
+ * Filters the iterator values.
+ *
+ * @return bool true if the value should be kept, false otherwise
+ */
+ public function accept()
+ {
+ return $this->isAccepted($this->current()->getFilename());
+ }
+
+ /**
+ * Converts glob to regexp.
+ *
+ * PCRE patterns are left unchanged.
+ * Glob strings are transformed with Glob::toRegex().
+ *
+ * @param string $str Pattern: glob or regexp
+ *
+ * @return string regexp corresponding to a given glob or regexp
+ */
+ protected function toRegex($str)
+ {
+ return $this->isRegex($str) ? $str : Glob::toRegex($str);
+ }
+}
diff --git a/vendor/symfony/finder/Iterator/FilterIterator.php b/vendor/symfony/finder/Iterator/FilterIterator.php
new file mode 100644
index 00000000..c16dd8fa
--- /dev/null
+++ b/vendor/symfony/finder/Iterator/FilterIterator.php
@@ -0,0 +1,60 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Iterator;
+
+/**
+ * This iterator just overrides the rewind method in order to correct a PHP bug,
+ * which existed before version 5.5.23/5.6.7.
+ *
+ * @see https://bugs.php.net/68557
+ *
+ * @author Alex Bogomazov
+ *
+ * @deprecated since 3.4, to be removed in 4.0.
+ */
+abstract class FilterIterator extends \FilterIterator
+{
+ /**
+ * This is a workaround for the problem with \FilterIterator leaving inner \FilesystemIterator in wrong state after
+ * rewind in some cases.
+ *
+ * @see FilterIterator::rewind()
+ */
+ public function rewind()
+ {
+ if (\PHP_VERSION_ID > 50607 || (\PHP_VERSION_ID > 50523 && \PHP_VERSION_ID < 50600)) {
+ parent::rewind();
+
+ return;
+ }
+
+ $iterator = $this;
+ while ($iterator instanceof \OuterIterator) {
+ $innerIterator = $iterator->getInnerIterator();
+
+ if ($innerIterator instanceof RecursiveDirectoryIterator) {
+ // this condition is necessary for iterators to work properly with non-local filesystems like ftp
+ if ($innerIterator->isRewindable()) {
+ $innerIterator->next();
+ $innerIterator->rewind();
+ }
+ } elseif ($innerIterator instanceof \FilesystemIterator) {
+ $innerIterator->next();
+ $innerIterator->rewind();
+ }
+
+ $iterator = $innerIterator;
+ }
+
+ parent::rewind();
+ }
+}
diff --git a/vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php b/vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php
new file mode 100644
index 00000000..fc885404
--- /dev/null
+++ b/vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php
@@ -0,0 +1,112 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Iterator;
+
+/**
+ * MultiplePcreFilterIterator filters files using patterns (regexps, globs or strings).
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+abstract class MultiplePcreFilterIterator extends FilterIterator
+{
+ protected $matchRegexps = array();
+ protected $noMatchRegexps = array();
+
+ /**
+ * @param \Iterator $iterator The Iterator to filter
+ * @param array $matchPatterns An array of patterns that need to match
+ * @param array $noMatchPatterns An array of patterns that need to not match
+ */
+ public function __construct(\Iterator $iterator, array $matchPatterns, array $noMatchPatterns)
+ {
+ foreach ($matchPatterns as $pattern) {
+ $this->matchRegexps[] = $this->toRegex($pattern);
+ }
+
+ foreach ($noMatchPatterns as $pattern) {
+ $this->noMatchRegexps[] = $this->toRegex($pattern);
+ }
+
+ parent::__construct($iterator);
+ }
+
+ /**
+ * Checks whether the string is accepted by the regex filters.
+ *
+ * If there is no regexps defined in the class, this method will accept the string.
+ * Such case can be handled by child classes before calling the method if they want to
+ * apply a different behavior.
+ *
+ * @param string $string The string to be matched against filters
+ *
+ * @return bool
+ */
+ protected function isAccepted($string)
+ {
+ // should at least not match one rule to exclude
+ foreach ($this->noMatchRegexps as $regex) {
+ if (preg_match($regex, $string)) {
+ return false;
+ }
+ }
+
+ // should at least match one rule
+ if ($this->matchRegexps) {
+ foreach ($this->matchRegexps as $regex) {
+ if (preg_match($regex, $string)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ // If there is no match rules, the file is accepted
+ return true;
+ }
+
+ /**
+ * Checks whether the string is a regex.
+ *
+ * @param string $str
+ *
+ * @return bool Whether the given string is a regex
+ */
+ protected function isRegex($str)
+ {
+ if (preg_match('/^(.{3,}?)[imsxuADU]*$/', $str, $m)) {
+ $start = substr($m[1], 0, 1);
+ $end = substr($m[1], -1);
+
+ if ($start === $end) {
+ return !preg_match('/[*?[:alnum:] \\\\]/', $start);
+ }
+
+ foreach (array(array('{', '}'), array('(', ')'), array('[', ']'), array('<', '>')) as $delimiters) {
+ if ($start === $delimiters[0] && $end === $delimiters[1]) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Converts string into regexp.
+ *
+ * @param string $str Pattern
+ *
+ * @return string regexp corresponding to a given string
+ */
+ abstract protected function toRegex($str);
+}
diff --git a/vendor/symfony/finder/Iterator/PathFilterIterator.php b/vendor/symfony/finder/Iterator/PathFilterIterator.php
new file mode 100644
index 00000000..dadfc8ed
--- /dev/null
+++ b/vendor/symfony/finder/Iterator/PathFilterIterator.php
@@ -0,0 +1,56 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Iterator;
+
+/**
+ * PathFilterIterator filters files by path patterns (e.g. some/special/dir).
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Włodzimierz Gajda <gajdaw@gajdaw.pl>
+ */
+class PathFilterIterator extends MultiplePcreFilterIterator
+{
+ /**
+ * Filters the iterator values.
+ *
+ * @return bool true if the value should be kept, false otherwise
+ */
+ public function accept()
+ {
+ $filename = $this->current()->getRelativePathname();
+
+ if ('\\' === DIRECTORY_SEPARATOR) {
+ $filename = str_replace('\\', '/', $filename);
+ }
+
+ return $this->isAccepted($filename);
+ }
+
+ /**
+ * Converts strings to regexp.
+ *
+ * PCRE patterns are left unchanged.
+ *
+ * Default conversion:
+ * 'lorem/ipsum/dolor' ==> 'lorem\/ipsum\/dolor/'
+ *
+ * Use only / as directory separator (on Windows also).
+ *
+ * @param string $str Pattern: regexp or dirname
+ *
+ * @return string regexp corresponding to a given string or regexp
+ */
+ protected function toRegex($str)
+ {
+ return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
+ }
+}
diff --git a/vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php b/vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php
new file mode 100644
index 00000000..c1c0e2f1
--- /dev/null
+++ b/vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php
@@ -0,0 +1,154 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Iterator;
+
+use Symfony\Component\Finder\Exception\AccessDeniedException;
+use Symfony\Component\Finder\SplFileInfo;
+
+/**
+ * Extends the \RecursiveDirectoryIterator to support relative paths.
+ *
+ * @author Victor Berchet <victor@suumit.com>
+ */
+class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
+{
+ /**
+ * @var bool
+ */
+ private $ignoreUnreadableDirs;
+
+ /**
+ * @var bool
+ */
+ private $rewindable;
+
+ // these 3 properties take part of the performance optimization to avoid redoing the same work in all iterations
+ private $rootPath;
+ private $subPath;
+ private $directorySeparator = '/';
+
+ /**
+ * @param string $path
+ * @param int $flags
+ * @param bool $ignoreUnreadableDirs
+ *
+ * @throws \RuntimeException
+ */
+ public function __construct($path, $flags, $ignoreUnreadableDirs = false)
+ {
+ if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) {
+ throw new \RuntimeException('This iterator only support returning current as fileinfo.');
+ }
+
+ parent::__construct($path, $flags);
+ $this->ignoreUnreadableDirs = $ignoreUnreadableDirs;
+ $this->rootPath = $path;
+ if ('/' !== DIRECTORY_SEPARATOR && !($flags & self::UNIX_PATHS)) {
+ $this->directorySeparator = DIRECTORY_SEPARATOR;
+ }
+ }
+
+ /**
+ * Return an instance of SplFileInfo with support for relative paths.
+ *
+ * @return SplFileInfo File information
+ */
+ public function current()
+ {
+ // the logic here avoids redoing the same work in all iterations
+
+ if (null === $subPathname = $this->subPath) {
+ $subPathname = $this->subPath = (string) $this->getSubPath();
+ }
+ if ('' !== $subPathname) {
+ $subPathname .= $this->directorySeparator;
+ }
+ $subPathname .= $this->getFilename();
+
+ return new SplFileInfo($this->rootPath.$this->directorySeparator.$subPathname, $this->subPath, $subPathname);
+ }
+
+ /**
+ * @return \RecursiveIterator
+ *
+ * @throws AccessDeniedException
+ */
+ public function getChildren()
+ {
+ try {
+ $children = parent::getChildren();
+
+ if ($children instanceof self) {
+ // parent method will call the constructor with default arguments, so unreadable dirs won't be ignored anymore
+ $children->ignoreUnreadableDirs = $this->ignoreUnreadableDirs;
+
+ // performance optimization to avoid redoing the same work in all children
+ $children->rewindable = &$this->rewindable;
+ $children->rootPath = $this->rootPath;
+ }
+
+ return $children;
+ } catch (\UnexpectedValueException $e) {
+ if ($this->ignoreUnreadableDirs) {
+ // If directory is unreadable and finder is set to ignore it, a fake empty content is returned.
+ return new \RecursiveArrayIterator(array());
+ } else {
+ throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e);
+ }
+ }
+ }
+
+ /**
+ * Do nothing for non rewindable stream.
+ */
+ public function rewind()
+ {
+ if (false === $this->isRewindable()) {
+ return;
+ }
+
+ // @see https://bugs.php.net/68557
+ if (\PHP_VERSION_ID < 50523 || \PHP_VERSION_ID >= 50600 && \PHP_VERSION_ID < 50607) {
+ parent::next();
+ }
+
+ parent::rewind();
+ }
+
+ /**
+ * Checks if the stream is rewindable.
+ *
+ * @return bool true when the stream is rewindable, false otherwise
+ */
+ public function isRewindable()
+ {
+ if (null !== $this->rewindable) {
+ return $this->rewindable;
+ }
+
+ // workaround for an HHVM bug, should be removed when https://github.com/facebook/hhvm/issues/7281 is fixed
+ if ('' === $this->getPath()) {
+ return $this->rewindable = false;
+ }
+
+ if (false !== $stream = @opendir($this->getPath())) {
+ $infos = stream_get_meta_data($stream);
+ closedir($stream);
+
+ if ($infos['seekable']) {
+ return $this->rewindable = true;
+ }
+ }
+
+ return $this->rewindable = false;
+ }
+}
diff --git a/vendor/symfony/finder/Iterator/SizeRangeFilterIterator.php b/vendor/symfony/finder/Iterator/SizeRangeFilterIterator.php
new file mode 100644
index 00000000..bd1a7fb7
--- /dev/null
+++ b/vendor/symfony/finder/Iterator/SizeRangeFilterIterator.php
@@ -0,0 +1,57 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Iterator;
+
+use Symfony\Component\Finder\Comparator\NumberComparator;
+
+/**
+ * SizeRangeFilterIterator filters out files that are not in the given size range.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class SizeRangeFilterIterator extends FilterIterator
+{
+ private $comparators = array();
+
+ /**
+ * @param \Iterator $iterator The Iterator to filter
+ * @param NumberComparator[] $comparators An array of NumberComparator instances
+ */
+ public function __construct(\Iterator $iterator, array $comparators)
+ {
+ $this->comparators = $comparators;
+
+ parent::__construct($iterator);
+ }
+
+ /**
+ * Filters the iterator values.
+ *
+ * @return bool true if the value should be kept, false otherwise
+ */
+ public function accept()
+ {
+ $fileinfo = $this->current();
+ if (!$fileinfo->isFile()) {
+ return true;
+ }
+
+ $filesize = $fileinfo->getSize();
+ foreach ($this->comparators as $compare) {
+ if (!$compare->test($filesize)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/vendor/symfony/finder/Iterator/SortableIterator.php b/vendor/symfony/finder/Iterator/SortableIterator.php
new file mode 100644
index 00000000..c2f54b93
--- /dev/null
+++ b/vendor/symfony/finder/Iterator/SortableIterator.php
@@ -0,0 +1,80 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Iterator;
+
+/**
+ * SortableIterator applies a sort on a given Iterator.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class SortableIterator implements \IteratorAggregate
+{
+ const SORT_BY_NAME = 1;
+ const SORT_BY_TYPE = 2;
+ const SORT_BY_ACCESSED_TIME = 3;
+ const SORT_BY_CHANGED_TIME = 4;
+ const SORT_BY_MODIFIED_TIME = 5;
+
+ private $iterator;
+ private $sort;
+
+ /**
+ * @param \Traversable $iterator The Iterator to filter
+ * @param int|callable $sort The sort type (SORT_BY_NAME, SORT_BY_TYPE, or a PHP callback)
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function __construct(\Traversable $iterator, $sort)
+ {
+ $this->iterator = $iterator;
+
+ if (self::SORT_BY_NAME === $sort) {
+ $this->sort = function ($a, $b) {
+ return strcmp($a->getRealpath() ?: $a->getPathname(), $b->getRealpath() ?: $b->getPathname());
+ };
+ } elseif (self::SORT_BY_TYPE === $sort) {
+ $this->sort = function ($a, $b) {
+ if ($a->isDir() && $b->isFile()) {
+ return -1;
+ } elseif ($a->isFile() && $b->isDir()) {
+ return 1;
+ }
+
+ return strcmp($a->getRealpath() ?: $a->getPathname(), $b->getRealpath() ?: $b->getPathname());
+ };
+ } elseif (self::SORT_BY_ACCESSED_TIME === $sort) {
+ $this->sort = function ($a, $b) {
+ return $a->getATime() - $b->getATime();
+ };
+ } elseif (self::SORT_BY_CHANGED_TIME === $sort) {
+ $this->sort = function ($a, $b) {
+ return $a->getCTime() - $b->getCTime();
+ };
+ } elseif (self::SORT_BY_MODIFIED_TIME === $sort) {
+ $this->sort = function ($a, $b) {
+ return $a->getMTime() - $b->getMTime();
+ };
+ } elseif (is_callable($sort)) {
+ $this->sort = $sort;
+ } else {
+ throw new \InvalidArgumentException('The SortableIterator takes a PHP callable or a valid built-in sort algorithm as an argument.');
+ }
+ }
+
+ public function getIterator()
+ {
+ $array = iterator_to_array($this->iterator, true);
+ uasort($array, $this->sort);
+
+ return new \ArrayIterator($array);
+ }
+}
diff --git a/vendor/symfony/finder/LICENSE b/vendor/symfony/finder/LICENSE
new file mode 100644
index 00000000..17d16a13
--- /dev/null
+++ b/vendor/symfony/finder/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2004-2017 Fabien Potencier
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/symfony/finder/README.md b/vendor/symfony/finder/README.md
new file mode 100644
index 00000000..0b19c752
--- /dev/null
+++ b/vendor/symfony/finder/README.md
@@ -0,0 +1,14 @@
+Finder Component
+================
+
+The Finder component finds files and directories via an intuitive fluent
+interface.
+
+Resources
+---------
+
+ * [Documentation](https://symfony.com/doc/current/components/finder.html)
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/symfony/issues) and
+ [send Pull Requests](https://github.com/symfony/symfony/pulls)
+ in the [main Symfony repository](https://github.com/symfony/symfony)
diff --git a/vendor/symfony/finder/SplFileInfo.php b/vendor/symfony/finder/SplFileInfo.php
new file mode 100644
index 00000000..19f95e26
--- /dev/null
+++ b/vendor/symfony/finder/SplFileInfo.php
@@ -0,0 +1,79 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder;
+
+/**
+ * Extends \SplFileInfo to support relative paths.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class SplFileInfo extends \SplFileInfo
+{
+ private $relativePath;
+ private $relativePathname;
+
+ /**
+ * @param string $file The file name
+ * @param string $relativePath The relative path
+ * @param string $relativePathname The relative path name
+ */
+ public function __construct($file, $relativePath, $relativePathname)
+ {
+ parent::__construct($file);
+ $this->relativePath = $relativePath;
+ $this->relativePathname = $relativePathname;
+ }
+
+ /**
+ * Returns the relative path.
+ *
+ * This path does not contain the file name.
+ *
+ * @return string the relative path
+ */
+ public function getRelativePath()
+ {
+ return $this->relativePath;
+ }
+
+ /**
+ * Returns the relative path name.
+ *
+ * This path contains the file name.
+ *
+ * @return string the relative path name
+ */
+ public function getRelativePathname()
+ {
+ return $this->relativePathname;
+ }
+
+ /**
+ * Returns the contents of the file.
+ *
+ * @return string the contents of the file
+ *
+ * @throws \RuntimeException
+ */
+ public function getContents()
+ {
+ $level = error_reporting(0);
+ $content = file_get_contents($this->getPathname());
+ error_reporting($level);
+ if (false === $content) {
+ $error = error_get_last();
+ throw new \RuntimeException($error['message']);
+ }
+
+ return $content;
+ }
+}
diff --git a/vendor/symfony/finder/Tests/Comparator/ComparatorTest.php b/vendor/symfony/finder/Tests/Comparator/ComparatorTest.php
new file mode 100644
index 00000000..656fc57a
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Comparator/ComparatorTest.php
@@ -0,0 +1,65 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Comparator;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Finder\Comparator\Comparator;
+
+class ComparatorTest extends TestCase
+{
+ public function testGetSetOperator()
+ {
+ $comparator = new Comparator();
+ try {
+ $comparator->setOperator('foo');
+ $this->fail('->setOperator() throws an \InvalidArgumentException if the operator is not valid.');
+ } catch (\Exception $e) {
+ $this->assertInstanceOf('InvalidArgumentException', $e, '->setOperator() throws an \InvalidArgumentException if the operator is not valid.');
+ }
+
+ $comparator = new Comparator();
+ $comparator->setOperator('>');
+ $this->assertEquals('>', $comparator->getOperator(), '->getOperator() returns the current operator');
+ }
+
+ public function testGetSetTarget()
+ {
+ $comparator = new Comparator();
+ $comparator->setTarget(8);
+ $this->assertEquals(8, $comparator->getTarget(), '->getTarget() returns the target');
+ }
+
+ /**
+ * @dataProvider getTestData
+ */
+ public function testTest($operator, $target, $match, $noMatch)
+ {
+ $c = new Comparator();
+ $c->setOperator($operator);
+ $c->setTarget($target);
+
+ foreach ($match as $m) {
+ $this->assertTrue($c->test($m), '->test() tests a string against the expression');
+ }
+
+ foreach ($noMatch as $m) {
+ $this->assertFalse($c->test($m), '->test() tests a string against the expression');
+ }
+ }
+
+ public function getTestData()
+ {
+ return array(
+ array('<', '1000', array('500', '999'), array('1000', '1500')),
+ );
+ }
+}
diff --git a/vendor/symfony/finder/Tests/Comparator/DateComparatorTest.php b/vendor/symfony/finder/Tests/Comparator/DateComparatorTest.php
new file mode 100644
index 00000000..8a6c1ddf
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Comparator/DateComparatorTest.php
@@ -0,0 +1,64 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Comparator;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Finder\Comparator\DateComparator;
+
+class DateComparatorTest extends TestCase
+{
+ public function testConstructor()
+ {
+ try {
+ new DateComparator('foobar');
+ $this->fail('__construct() throws an \InvalidArgumentException if the test expression is not valid.');
+ } catch (\Exception $e) {
+ $this->assertInstanceOf('InvalidArgumentException', $e, '__construct() throws an \InvalidArgumentException if the test expression is not valid.');
+ }
+
+ try {
+ new DateComparator('');
+ $this->fail('__construct() throws an \InvalidArgumentException if the test expression is not valid.');
+ } catch (\Exception $e) {
+ $this->assertInstanceOf('InvalidArgumentException', $e, '__construct() throws an \InvalidArgumentException if the test expression is not valid.');
+ }
+ }
+
+ /**
+ * @dataProvider getTestData
+ */
+ public function testTest($test, $match, $noMatch)
+ {
+ $c = new DateComparator($test);
+
+ foreach ($match as $m) {
+ $this->assertTrue($c->test($m), '->test() tests a string against the expression');
+ }
+
+ foreach ($noMatch as $m) {
+ $this->assertFalse($c->test($m), '->test() tests a string against the expression');
+ }
+ }
+
+ public function getTestData()
+ {
+ return array(
+ array('< 2005-10-10', array(strtotime('2005-10-09')), array(strtotime('2005-10-15'))),
+ array('until 2005-10-10', array(strtotime('2005-10-09')), array(strtotime('2005-10-15'))),
+ array('before 2005-10-10', array(strtotime('2005-10-09')), array(strtotime('2005-10-15'))),
+ array('> 2005-10-10', array(strtotime('2005-10-15')), array(strtotime('2005-10-09'))),
+ array('after 2005-10-10', array(strtotime('2005-10-15')), array(strtotime('2005-10-09'))),
+ array('since 2005-10-10', array(strtotime('2005-10-15')), array(strtotime('2005-10-09'))),
+ array('!= 2005-10-10', array(strtotime('2005-10-11')), array(strtotime('2005-10-10'))),
+ );
+ }
+}
diff --git a/vendor/symfony/finder/Tests/Comparator/NumberComparatorTest.php b/vendor/symfony/finder/Tests/Comparator/NumberComparatorTest.php
new file mode 100644
index 00000000..30a75c73
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Comparator/NumberComparatorTest.php
@@ -0,0 +1,108 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Comparator;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Finder\Comparator\NumberComparator;
+
+class NumberComparatorTest extends TestCase
+{
+ /**
+ * @dataProvider getConstructorTestData
+ */
+ public function testConstructor($successes, $failures)
+ {
+ foreach ($successes as $s) {
+ new NumberComparator($s);
+ }
+
+ foreach ($failures as $f) {
+ try {
+ new NumberComparator($f);
+ $this->fail('__construct() throws an \InvalidArgumentException if the test expression is not valid.');
+ } catch (\Exception $e) {
+ $this->assertInstanceOf('InvalidArgumentException', $e, '__construct() throws an \InvalidArgumentException if the test expression is not valid.');
+ }
+ }
+ }
+
+ /**
+ * @dataProvider getTestData
+ */
+ public function testTest($test, $match, $noMatch)
+ {
+ $c = new NumberComparator($test);
+
+ foreach ($match as $m) {
+ $this->assertTrue($c->test($m), '->test() tests a string against the expression');
+ }
+
+ foreach ($noMatch as $m) {
+ $this->assertFalse($c->test($m), '->test() tests a string against the expression');
+ }
+ }
+
+ public function getTestData()
+ {
+ return array(
+ array('< 1000', array('500', '999'), array('1000', '1500')),
+
+ array('< 1K', array('500', '999'), array('1000', '1500')),
+ array('<1k', array('500', '999'), array('1000', '1500')),
+ array(' < 1 K ', array('500', '999'), array('1000', '1500')),
+ array('<= 1K', array('1000'), array('1001')),
+ array('> 1K', array('1001'), array('1000')),
+ array('>= 1K', array('1000'), array('999')),
+
+ array('< 1KI', array('500', '1023'), array('1024', '1500')),
+ array('<= 1KI', array('1024'), array('1025')),
+ array('> 1KI', array('1025'), array('1024')),
+ array('>= 1KI', array('1024'), array('1023')),
+
+ array('1KI', array('1024'), array('1023', '1025')),
+ array('==1KI', array('1024'), array('1023', '1025')),
+
+ array('==1m', array('1000000'), array('999999', '1000001')),
+ array('==1mi', array(1024 * 1024), array(1024 * 1024 - 1, 1024 * 1024 + 1)),
+
+ array('==1g', array('1000000000'), array('999999999', '1000000001')),
+ array('==1gi', array(1024 * 1024 * 1024), array(1024 * 1024 * 1024 - 1, 1024 * 1024 * 1024 + 1)),
+
+ array('!= 1000', array('500', '999'), array('1000')),
+ );
+ }
+
+ public function getConstructorTestData()
+ {
+ return array(
+ array(
+ array(
+ '1', '0',
+ '3.5', '33.55', '123.456', '123456.78',
+ '.1', '.123',
+ '.0', '0.0',
+ '1.', '0.', '123.',
+ '==1', '!=1', '<1', '>1', '<=1', '>=1',
+ '==1k', '==1ki', '==1m', '==1mi', '==1g', '==1gi',
+ '1k', '1ki', '1m', '1mi', '1g', '1gi',
+ ),
+ array(
+ false, null, '',
+ ' ', 'foobar',
+ '=1', '===1',
+ '0 . 1', '123 .45', '234. 567',
+ '..', '.0.', '0.1.2',
+ ),
+ ),
+ );
+ }
+}
diff --git a/vendor/symfony/finder/Tests/FinderTest.php b/vendor/symfony/finder/Tests/FinderTest.php
new file mode 100644
index 00000000..7e75f141
--- /dev/null
+++ b/vendor/symfony/finder/Tests/FinderTest.php
@@ -0,0 +1,698 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests;
+
+use Symfony\Component\Finder\Finder;
+
+class FinderTest extends Iterator\RealIteratorTestCase
+{
+ public function testCreate()
+ {
+ $this->assertInstanceOf('Symfony\Component\Finder\Finder', Finder::create());
+ }
+
+ public function testDirectories()
+ {
+ $finder = $this->buildFinder();
+ $this->assertSame($finder, $finder->directories());
+ $this->assertIterator($this->toAbsolute(array('foo', 'toto')), $finder->in(self::$tmpDir)->getIterator());
+
+ $finder = $this->buildFinder();
+ $finder->directories();
+ $finder->files();
+ $finder->directories();
+ $this->assertIterator($this->toAbsolute(array('foo', 'toto')), $finder->in(self::$tmpDir)->getIterator());
+ }
+
+ public function testFiles()
+ {
+ $finder = $this->buildFinder();
+ $this->assertSame($finder, $finder->files());
+ $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'test.py', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+
+ $finder = $this->buildFinder();
+ $finder->files();
+ $finder->directories();
+ $finder->files();
+ $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'test.py', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+ }
+
+ public function testDepth()
+ {
+ $finder = $this->buildFinder();
+ $this->assertSame($finder, $finder->depth('< 1'));
+ $this->assertIterator($this->toAbsolute(array('foo', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+
+ $finder = $this->buildFinder();
+ $this->assertSame($finder, $finder->depth('<= 0'));
+ $this->assertIterator($this->toAbsolute(array('foo', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+
+ $finder = $this->buildFinder();
+ $this->assertSame($finder, $finder->depth('>= 1'));
+ $this->assertIterator($this->toAbsolute(array('foo/bar.tmp')), $finder->in(self::$tmpDir)->getIterator());
+
+ $finder = $this->buildFinder();
+ $finder->depth('< 1')->depth('>= 1');
+ $this->assertIterator(array(), $finder->in(self::$tmpDir)->getIterator());
+ }
+
+ public function testName()
+ {
+ $finder = $this->buildFinder();
+ $this->assertSame($finder, $finder->name('*.php'));
+ $this->assertIterator($this->toAbsolute(array('test.php')), $finder->in(self::$tmpDir)->getIterator());
+
+ $finder = $this->buildFinder();
+ $finder->name('test.ph*');
+ $finder->name('test.py');
+ $this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator());
+
+ $finder = $this->buildFinder();
+ $finder->name('~^test~i');
+ $this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator());
+
+ $finder = $this->buildFinder();
+ $finder->name('~\\.php$~i');
+ $this->assertIterator($this->toAbsolute(array('test.php')), $finder->in(self::$tmpDir)->getIterator());
+
+ $finder = $this->buildFinder();
+ $finder->name('test.p{hp,y}');
+ $this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator());
+ }
+
+ public function testNotName()
+ {
+ $finder = $this->buildFinder();
+ $this->assertSame($finder, $finder->notName('*.php'));
+ $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+
+ $finder = $this->buildFinder();
+ $finder->notName('*.php');
+ $finder->notName('*.py');
+ $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+
+ $finder = $this->buildFinder();
+ $finder->name('test.ph*');
+ $finder->name('test.py');
+ $finder->notName('*.php');
+ $finder->notName('*.py');
+ $this->assertIterator(array(), $finder->in(self::$tmpDir)->getIterator());
+
+ $finder = $this->buildFinder();
+ $finder->name('test.ph*');
+ $finder->name('test.py');
+ $finder->notName('*.p{hp,y}');
+ $this->assertIterator(array(), $finder->in(self::$tmpDir)->getIterator());
+ }
+
+ /**
+ * @dataProvider getRegexNameTestData
+ */
+ public function testRegexName($regex)
+ {
+ $finder = $this->buildFinder();
+ $finder->name($regex);
+ $this->assertIterator($this->toAbsolute(array('test.py', 'test.php')), $finder->in(self::$tmpDir)->getIterator());
+ }
+
+ public function testSize()
+ {
+ $finder = $this->buildFinder();
+ $this->assertSame($finder, $finder->files()->size('< 1K')->size('> 500'));
+ $this->assertIterator($this->toAbsolute(array('test.php')), $finder->in(self::$tmpDir)->getIterator());
+ }
+
+ public function testDate()
+ {
+ $finder = $this->buildFinder();
+ $this->assertSame($finder, $finder->files()->date('until last month'));
+ $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php')), $finder->in(self::$tmpDir)->getIterator());
+ }
+
+ public function testExclude()
+ {
+ $finder = $this->buildFinder();
+ $this->assertSame($finder, $finder->exclude('foo'));
+ $this->assertIterator($this->toAbsolute(array('test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+ }
+
+ public function testIgnoreVCS()
+ {
+ $finder = $this->buildFinder();
+ $this->assertSame($finder, $finder->ignoreVCS(false)->ignoreDotFiles(false));
+ $this->assertIterator($this->toAbsolute(array('.git', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'toto/.git', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+
+ $finder = $this->buildFinder();
+ $finder->ignoreVCS(false)->ignoreVCS(false)->ignoreDotFiles(false);
+ $this->assertIterator($this->toAbsolute(array('.git', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'toto/.git', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+
+ $finder = $this->buildFinder();
+ $this->assertSame($finder, $finder->ignoreVCS(true)->ignoreDotFiles(false));
+ $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+ }
+
+ public function testIgnoreDotFiles()
+ {
+ $finder = $this->buildFinder();
+ $this->assertSame($finder, $finder->ignoreDotFiles(false)->ignoreVCS(false));
+ $this->assertIterator($this->toAbsolute(array('.git', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'toto/.git', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+
+ $finder = $this->buildFinder();
+ $finder->ignoreDotFiles(false)->ignoreDotFiles(false)->ignoreVCS(false);
+ $this->assertIterator($this->toAbsolute(array('.git', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'toto/.git', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+
+ $finder = $this->buildFinder();
+ $this->assertSame($finder, $finder->ignoreDotFiles(true)->ignoreVCS(false));
+ $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+ }
+
+ public function testSortByName()
+ {
+ $finder = $this->buildFinder();
+ $this->assertSame($finder, $finder->sortByName());
+ $this->assertIterator($this->toAbsolute(array('foo', 'foo bar', 'foo/bar.tmp', 'test.php', 'test.py', 'toto')), $finder->in(self::$tmpDir)->getIterator());
+ }
+
+ public function testSortByType()
+ {
+ $finder = $this->buildFinder();
+ $this->assertSame($finder, $finder->sortByType());
+ $this->assertIterator($this->toAbsolute(array('foo', 'foo bar', 'toto', 'foo/bar.tmp', 'test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator());
+ }
+
+ public function testSortByAccessedTime()
+ {
+ $finder = $this->buildFinder();
+ $this->assertSame($finder, $finder->sortByAccessedTime());
+ $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'toto', 'test.py', 'foo', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+ }
+
+ public function testSortByChangedTime()
+ {
+ $finder = $this->buildFinder();
+ $this->assertSame($finder, $finder->sortByChangedTime());
+ $this->assertIterator($this->toAbsolute(array('toto', 'test.py', 'test.php', 'foo/bar.tmp', 'foo', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+ }
+
+ public function testSortByModifiedTime()
+ {
+ $finder = $this->buildFinder();
+ $this->assertSame($finder, $finder->sortByModifiedTime());
+ $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'toto', 'test.py', 'foo', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+ }
+
+ public function testSort()
+ {
+ $finder = $this->buildFinder();
+ $this->assertSame($finder, $finder->sort(function (\SplFileInfo $a, \SplFileInfo $b) { return strcmp($a->getRealPath(), $b->getRealPath()); }));
+ $this->assertIterator($this->toAbsolute(array('foo', 'foo bar', 'foo/bar.tmp', 'test.php', 'test.py', 'toto')), $finder->in(self::$tmpDir)->getIterator());
+ }
+
+ public function testFilter()
+ {
+ $finder = $this->buildFinder();
+ $this->assertSame($finder, $finder->filter(function (\SplFileInfo $f) { return false !== strpos($f, 'test'); }));
+ $this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator());
+ }
+
+ public function testFollowLinks()
+ {
+ if ('\\' == DIRECTORY_SEPARATOR) {
+ $this->markTestSkipped('symlinks are not supported on Windows');
+ }
+
+ $finder = $this->buildFinder();
+ $this->assertSame($finder, $finder->followLinks());
+ $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
+ }
+
+ public function testIn()
+ {
+ $finder = $this->buildFinder();
+ $iterator = $finder->files()->name('*.php')->depth('< 1')->in(array(self::$tmpDir, __DIR__))->getIterator();
+
+ $expected = array(
+ self::$tmpDir.DIRECTORY_SEPARATOR.'test.php',
+ __DIR__.DIRECTORY_SEPARATOR.'FinderTest.php',
+ __DIR__.DIRECTORY_SEPARATOR.'GlobTest.php',
+ );
+
+ $this->assertIterator($expected, $iterator);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testInWithNonExistentDirectory()
+ {
+ $finder = new Finder();
+ $finder->in('foobar');
+ }
+
+ public function testInWithGlob()
+ {
+ $finder = $this->buildFinder();
+ $finder->in(array(__DIR__.'/Fixtures/*/B/C', __DIR__.'/Fixtures/*/*/B/C'))->getIterator();
+
+ $this->assertIterator($this->toAbsoluteFixtures(array('A/B/C/abc.dat', 'copy/A/B/C/abc.dat.copy')), $finder);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testInWithNonDirectoryGlob()
+ {
+ $finder = new Finder();
+ $finder->in(__DIR__.'/Fixtures/A/a*');
+ }
+
+ public function testInWithGlobBrace()
+ {
+ $finder = $this->buildFinder();
+ $finder->in(array(__DIR__.'/Fixtures/{A,copy/A}/B/C'))->getIterator();
+
+ $this->assertIterator($this->toAbsoluteFixtures(array('A/B/C/abc.dat', 'copy/A/B/C/abc.dat.copy')), $finder);
+ }
+
+ /**
+ * @expectedException \LogicException
+ */
+ public function testGetIteratorWithoutIn()
+ {
+ $finder = Finder::create();
+ $finder->getIterator();
+ }
+
+ public function testGetIterator()
+ {
+ $finder = $this->buildFinder();
+ $dirs = array();
+ foreach ($finder->directories()->in(self::$tmpDir) as $dir) {
+ $dirs[] = (string) $dir;
+ }
+
+ $expected = $this->toAbsolute(array('foo', 'toto'));
+
+ sort($dirs);
+ sort($expected);
+
+ $this->assertEquals($expected, $dirs, 'implements the \IteratorAggregate interface');
+
+ $finder = $this->buildFinder();
+ $this->assertEquals(2, iterator_count($finder->directories()->in(self::$tmpDir)), 'implements the \IteratorAggregate interface');
+
+ $finder = $this->buildFinder();
+ $a = iterator_to_array($finder->directories()->in(self::$tmpDir));
+ $a = array_values(array_map('strval', $a));
+ sort($a);
+ $this->assertEquals($expected, $a, 'implements the \IteratorAggregate interface');
+ }
+
+ public function testRelativePath()
+ {
+ $finder = $this->buildFinder()->in(self::$tmpDir);
+
+ $paths = array();
+
+ foreach ($finder as $file) {
+ $paths[] = $file->getRelativePath();
+ }
+
+ $ref = array('', '', '', '', 'foo', '');
+
+ sort($ref);
+ sort($paths);
+
+ $this->assertEquals($ref, $paths);
+ }
+
+ public function testRelativePathname()
+ {
+ $finder = $this->buildFinder()->in(self::$tmpDir)->sortByName();
+
+ $paths = array();
+
+ foreach ($finder as $file) {
+ $paths[] = $file->getRelativePathname();
+ }
+
+ $ref = array('test.php', 'toto', 'test.py', 'foo', 'foo'.DIRECTORY_SEPARATOR.'bar.tmp', 'foo bar');
+
+ sort($paths);
+ sort($ref);
+
+ $this->assertEquals($ref, $paths);
+ }
+
+ public function testAppendWithAFinder()
+ {
+ $finder = $this->buildFinder();
+ $finder->files()->in(self::$tmpDir.DIRECTORY_SEPARATOR.'foo');
+
+ $finder1 = $this->buildFinder();
+ $finder1->directories()->in(self::$tmpDir);
+
+ $finder = $finder->append($finder1);
+
+ $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'toto')), $finder->getIterator());
+ }
+
+ public function testAppendWithAnArray()
+ {
+ $finder = $this->buildFinder();
+ $finder->files()->in(self::$tmpDir.DIRECTORY_SEPARATOR.'foo');
+
+ $finder->append($this->toAbsolute(array('foo', 'toto')));
+
+ $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'toto')), $finder->getIterator());
+ }
+
+ public function testAppendReturnsAFinder()
+ {
+ $this->assertInstanceOf('Symfony\\Component\\Finder\\Finder', Finder::create()->append(array()));
+ }
+
+ public function testAppendDoesNotRequireIn()
+ {
+ $finder = $this->buildFinder();
+ $finder->in(self::$tmpDir.DIRECTORY_SEPARATOR.'foo');
+
+ $finder1 = Finder::create()->append($finder);
+
+ $this->assertIterator(iterator_to_array($finder->getIterator()), $finder1->getIterator());
+ }
+
+ public function testCountDirectories()
+ {
+ $directory = Finder::create()->directories()->in(self::$tmpDir);
+ $i = 0;
+
+ foreach ($directory as $dir) {
+ ++$i;
+ }
+
+ $this->assertCount($i, $directory);
+ }
+
+ public function testCountFiles()
+ {
+ $files = Finder::create()->files()->in(__DIR__.DIRECTORY_SEPARATOR.'Fixtures');
+ $i = 0;
+
+ foreach ($files as $file) {
+ ++$i;
+ }
+
+ $this->assertCount($i, $files);
+ }
+
+ /**
+ * @expectedException \LogicException
+ */
+ public function testCountWithoutIn()
+ {
+ $finder = Finder::create()->files();
+ count($finder);
+ }
+
+ public function testHasResults()
+ {
+ $finder = $this->buildFinder();
+ $finder->in(__DIR__);
+ $this->assertTrue($finder->hasResults());
+ }
+
+ public function testNoResults()
+ {
+ $finder = $this->buildFinder();
+ $finder->in(__DIR__)->name('DoesNotExist');
+ $this->assertFalse($finder->hasResults());
+ }
+
+ /**
+ * @dataProvider getContainsTestData
+ */
+ public function testContains($matchPatterns, $noMatchPatterns, $expected)
+ {
+ $finder = $this->buildFinder();
+ $finder->in(__DIR__.DIRECTORY_SEPARATOR.'Fixtures')
+ ->name('*.txt')->sortByName()
+ ->contains($matchPatterns)
+ ->notContains($noMatchPatterns);
+
+ $this->assertIterator($this->toAbsoluteFixtures($expected), $finder);
+ }
+
+ public function testContainsOnDirectory()
+ {
+ $finder = $this->buildFinder();
+ $finder->in(__DIR__)
+ ->directories()
+ ->name('Fixtures')
+ ->contains('abc');
+ $this->assertIterator(array(), $finder);
+ }
+
+ public function testNotContainsOnDirectory()
+ {
+ $finder = $this->buildFinder();
+ $finder->in(__DIR__)
+ ->directories()
+ ->name('Fixtures')
+ ->notContains('abc');
+ $this->assertIterator(array(), $finder);
+ }
+
+ /**
+ * Searching in multiple locations involves AppendIterator which does an unnecessary rewind which leaves FilterIterator
+ * with inner FilesystemIterator in an invalid state.
+ *
+ * @see https://bugs.php.net/68557
+ */
+ public function testMultipleLocations()
+ {
+ $locations = array(
+ self::$tmpDir.'/',
+ self::$tmpDir.'/toto/',
+ );
+
+ // it is expected that there are test.py test.php in the tmpDir
+ $finder = new Finder();
+ $finder->in($locations)
+ // the default flag IGNORE_DOT_FILES fixes the problem indirectly
+ // so we set it to false for better isolation
+ ->ignoreDotFiles(false)
+ ->depth('< 1')->name('test.php');
+
+ $this->assertCount(1, $finder);
+ }
+
+ /**
+ * Searching in multiple locations with sub directories involves
+ * AppendIterator which does an unnecessary rewind which leaves
+ * FilterIterator with inner FilesystemIterator in an invalid state.
+ *
+ * @see https://bugs.php.net/68557
+ */
+ public function testMultipleLocationsWithSubDirectories()
+ {
+ $locations = array(
+ __DIR__.'/Fixtures/one',
+ self::$tmpDir.DIRECTORY_SEPARATOR.'toto',
+ );
+
+ $finder = $this->buildFinder();
+ $finder->in($locations)->depth('< 10')->name('*.neon');
+
+ $expected = array(
+ __DIR__.'/Fixtures/one'.DIRECTORY_SEPARATOR.'b'.DIRECTORY_SEPARATOR.'c.neon',
+ __DIR__.'/Fixtures/one'.DIRECTORY_SEPARATOR.'b'.DIRECTORY_SEPARATOR.'d.neon',
+ );
+
+ $this->assertIterator($expected, $finder);
+ $this->assertIteratorInForeach($expected, $finder);
+ }
+
+ /**
+ * Iterator keys must be the file pathname.
+ */
+ public function testIteratorKeys()
+ {
+ $finder = $this->buildFinder()->in(self::$tmpDir);
+ foreach ($finder as $key => $file) {
+ $this->assertEquals($file->getPathname(), $key);
+ }
+ }
+
+ public function testRegexSpecialCharsLocationWithPathRestrictionContainingStartFlag()
+ {
+ $finder = $this->buildFinder();
+ $finder->in(__DIR__.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR.'r+e.gex[c]a(r)s')
+ ->path('/^dir/');
+
+ $expected = array('r+e.gex[c]a(r)s'.DIRECTORY_SEPARATOR.'dir', 'r+e.gex[c]a(r)s'.DIRECTORY_SEPARATOR.'dir'.DIRECTORY_SEPARATOR.'bar.dat');
+ $this->assertIterator($this->toAbsoluteFixtures($expected), $finder);
+ }
+
+ public function getContainsTestData()
+ {
+ return array(
+ array('', '', array()),
+ array('foo', 'bar', array()),
+ array('', 'foobar', array('dolor.txt', 'ipsum.txt', 'lorem.txt')),
+ array('lorem ipsum dolor sit amet', 'foobar', array('lorem.txt')),
+ array('sit', 'bar', array('dolor.txt', 'ipsum.txt', 'lorem.txt')),
+ array('dolor sit amet', '@^L@m', array('dolor.txt', 'ipsum.txt')),
+ array('/^lorem ipsum dolor sit amet$/m', 'foobar', array('lorem.txt')),
+ array('lorem', 'foobar', array('lorem.txt')),
+ array('', 'lorem', array('dolor.txt', 'ipsum.txt')),
+ array('ipsum dolor sit amet', '/^IPSUM/m', array('lorem.txt')),
+ );
+ }
+
+ public function getRegexNameTestData()
+ {
+ return array(
+ array('~.+\\.p.+~i'),
+ array('~t.*s~i'),
+ );
+ }
+
+ /**
+ * @dataProvider getTestPathData
+ */
+ public function testPath($matchPatterns, $noMatchPatterns, array $expected)
+ {
+ $finder = $this->buildFinder();
+ $finder->in(__DIR__.DIRECTORY_SEPARATOR.'Fixtures')
+ ->path($matchPatterns)
+ ->notPath($noMatchPatterns);
+
+ $this->assertIterator($this->toAbsoluteFixtures($expected), $finder);
+ }
+
+ public function getTestPathData()
+ {
+ return array(
+ array('', '', array()),
+ array('/^A\/B\/C/', '/C$/',
+ array('A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat'),
+ ),
+ array('/^A\/B/', 'foobar',
+ array(
+ 'A'.DIRECTORY_SEPARATOR.'B',
+ 'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C',
+ 'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'ab.dat',
+ 'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat',
+ ),
+ ),
+ array('A/B/C', 'foobar',
+ array(
+ 'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C',
+ 'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat',
+ 'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C',
+ 'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat.copy',
+ ),
+ ),
+ array('A/B', 'foobar',
+ array(
+ //dirs
+ 'A'.DIRECTORY_SEPARATOR.'B',
+ 'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C',
+ 'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B',
+ 'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C',
+ //files
+ 'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'ab.dat',
+ 'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat',
+ 'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'ab.dat.copy',
+ 'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat.copy',
+ ),
+ ),
+ array('/^with space\//', 'foobar',
+ array(
+ 'with space'.DIRECTORY_SEPARATOR.'foo.txt',
+ ),
+ ),
+ );
+ }
+
+ public function testAccessDeniedException()
+ {
+ if ('\\' === DIRECTORY_SEPARATOR) {
+ $this->markTestSkipped('chmod is not supported on Windows');
+ }
+
+ $finder = $this->buildFinder();
+ $finder->files()->in(self::$tmpDir);
+
+ // make 'foo' directory non-readable
+ $testDir = self::$tmpDir.DIRECTORY_SEPARATOR.'foo';
+ chmod($testDir, 0333);
+
+ if (false === $couldRead = is_readable($testDir)) {
+ try {
+ $this->assertIterator($this->toAbsolute(array('foo bar', 'test.php', 'test.py')), $finder->getIterator());
+ $this->fail('Finder should throw an exception when opening a non-readable directory.');
+ } catch (\Exception $e) {
+ $expectedExceptionClass = 'Symfony\\Component\\Finder\\Exception\\AccessDeniedException';
+ if ($e instanceof \PHPUnit_Framework_ExpectationFailedException) {
+ $this->fail(sprintf("Expected exception:\n%s\nGot:\n%s\nWith comparison failure:\n%s", $expectedExceptionClass, 'PHPUnit_Framework_ExpectationFailedException', $e->getComparisonFailure()->getExpectedAsString()));
+ }
+
+ if ($e instanceof \PHPUnit\Framework\ExpectationFailedException) {
+ $this->fail(sprintf("Expected exception:\n%s\nGot:\n%s\nWith comparison failure:\n%s", $expectedExceptionClass, '\PHPUnit\Framework\ExpectationFailedException', $e->getComparisonFailure()->getExpectedAsString()));
+ }
+
+ $this->assertInstanceOf($expectedExceptionClass, $e);
+ }
+ }
+
+ // restore original permissions
+ chmod($testDir, 0777);
+ clearstatcache($testDir);
+
+ if ($couldRead) {
+ $this->markTestSkipped('could read test files while test requires unreadable');
+ }
+ }
+
+ public function testIgnoredAccessDeniedException()
+ {
+ if ('\\' === DIRECTORY_SEPARATOR) {
+ $this->markTestSkipped('chmod is not supported on Windows');
+ }
+
+ $finder = $this->buildFinder();
+ $finder->files()->ignoreUnreadableDirs()->in(self::$tmpDir);
+
+ // make 'foo' directory non-readable
+ $testDir = self::$tmpDir.DIRECTORY_SEPARATOR.'foo';
+ chmod($testDir, 0333);
+
+ if (false === ($couldRead = is_readable($testDir))) {
+ $this->assertIterator($this->toAbsolute(array('foo bar', 'test.php', 'test.py')), $finder->getIterator());
+ }
+
+ // restore original permissions
+ chmod($testDir, 0777);
+ clearstatcache($testDir);
+
+ if ($couldRead) {
+ $this->markTestSkipped('could read test files while test requires unreadable');
+ }
+ }
+
+ protected function buildFinder()
+ {
+ return Finder::create();
+ }
+}
diff --git a/vendor/symfony/finder/Tests/Fixtures/.dot/a b/vendor/symfony/finder/Tests/Fixtures/.dot/a
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Fixtures/.dot/a
diff --git a/vendor/symfony/finder/Tests/Fixtures/.dot/b/c.neon b/vendor/symfony/finder/Tests/Fixtures/.dot/b/c.neon
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Fixtures/.dot/b/c.neon
diff --git a/vendor/symfony/finder/Tests/Fixtures/.dot/b/d.neon b/vendor/symfony/finder/Tests/Fixtures/.dot/b/d.neon
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Fixtures/.dot/b/d.neon
diff --git a/vendor/symfony/finder/Tests/Fixtures/A/B/C/abc.dat b/vendor/symfony/finder/Tests/Fixtures/A/B/C/abc.dat
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Fixtures/A/B/C/abc.dat
diff --git a/vendor/symfony/finder/Tests/Fixtures/A/B/ab.dat b/vendor/symfony/finder/Tests/Fixtures/A/B/ab.dat
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Fixtures/A/B/ab.dat
diff --git a/vendor/symfony/finder/Tests/Fixtures/A/a.dat b/vendor/symfony/finder/Tests/Fixtures/A/a.dat
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Fixtures/A/a.dat
diff --git a/vendor/symfony/finder/Tests/Fixtures/copy/A/B/C/abc.dat.copy b/vendor/symfony/finder/Tests/Fixtures/copy/A/B/C/abc.dat.copy
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Fixtures/copy/A/B/C/abc.dat.copy
diff --git a/vendor/symfony/finder/Tests/Fixtures/copy/A/B/ab.dat.copy b/vendor/symfony/finder/Tests/Fixtures/copy/A/B/ab.dat.copy
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Fixtures/copy/A/B/ab.dat.copy
diff --git a/vendor/symfony/finder/Tests/Fixtures/copy/A/a.dat.copy b/vendor/symfony/finder/Tests/Fixtures/copy/A/a.dat.copy
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Fixtures/copy/A/a.dat.copy
diff --git a/vendor/symfony/finder/Tests/Fixtures/dolor.txt b/vendor/symfony/finder/Tests/Fixtures/dolor.txt
new file mode 100644
index 00000000..658bec69
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Fixtures/dolor.txt
@@ -0,0 +1,2 @@
+dolor sit amet
+DOLOR SIT AMET \ No newline at end of file
diff --git a/vendor/symfony/finder/Tests/Fixtures/ipsum.txt b/vendor/symfony/finder/Tests/Fixtures/ipsum.txt
new file mode 100644
index 00000000..c7f392d6
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Fixtures/ipsum.txt
@@ -0,0 +1,2 @@
+ipsum dolor sit amet
+IPSUM DOLOR SIT AMET \ No newline at end of file
diff --git a/vendor/symfony/finder/Tests/Fixtures/lorem.txt b/vendor/symfony/finder/Tests/Fixtures/lorem.txt
new file mode 100644
index 00000000..2991a2ca
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Fixtures/lorem.txt
@@ -0,0 +1,2 @@
+lorem ipsum dolor sit amet
+LOREM IPSUM DOLOR SIT AMET \ No newline at end of file
diff --git a/vendor/symfony/finder/Tests/Fixtures/one/.dot b/vendor/symfony/finder/Tests/Fixtures/one/.dot
new file mode 100644
index 00000000..1028065f
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Fixtures/one/.dot
@@ -0,0 +1 @@
+.dot \ No newline at end of file
diff --git a/vendor/symfony/finder/Tests/Fixtures/one/a b/vendor/symfony/finder/Tests/Fixtures/one/a
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Fixtures/one/a
diff --git a/vendor/symfony/finder/Tests/Fixtures/one/b/c.neon b/vendor/symfony/finder/Tests/Fixtures/one/b/c.neon
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Fixtures/one/b/c.neon
diff --git a/vendor/symfony/finder/Tests/Fixtures/one/b/d.neon b/vendor/symfony/finder/Tests/Fixtures/one/b/d.neon
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Fixtures/one/b/d.neon
diff --git a/vendor/symfony/finder/Tests/Fixtures/r+e.gex[c]a(r)s/dir/bar.dat b/vendor/symfony/finder/Tests/Fixtures/r+e.gex[c]a(r)s/dir/bar.dat
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Fixtures/r+e.gex[c]a(r)s/dir/bar.dat
diff --git a/vendor/symfony/finder/Tests/Fixtures/with space/foo.txt b/vendor/symfony/finder/Tests/Fixtures/with space/foo.txt
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Fixtures/with space/foo.txt
diff --git a/vendor/symfony/finder/Tests/GlobTest.php b/vendor/symfony/finder/Tests/GlobTest.php
new file mode 100644
index 00000000..d48ac1fc
--- /dev/null
+++ b/vendor/symfony/finder/Tests/GlobTest.php
@@ -0,0 +1,95 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Finder\Finder;
+use Symfony\Component\Finder\Glob;
+
+class GlobTest extends TestCase
+{
+ public function testGlobToRegexDelimiters()
+ {
+ $this->assertEquals('#^(?=[^\.])\#$#', Glob::toRegex('#'));
+ $this->assertEquals('#^\.[^/]*$#', Glob::toRegex('.*'));
+ $this->assertEquals('^\.[^/]*$', Glob::toRegex('.*', true, true, ''));
+ $this->assertEquals('/^\.[^/]*$/', Glob::toRegex('.*', true, true, '/'));
+ }
+
+ public function testGlobToRegexDoubleStarStrictDots()
+ {
+ $finder = new Finder();
+ $finder->ignoreDotFiles(false);
+ $regex = Glob::toRegex('/**/*.neon');
+
+ foreach ($finder->in(__DIR__) as $k => $v) {
+ $k = str_replace(DIRECTORY_SEPARATOR, '/', $k);
+ if (preg_match($regex, substr($k, strlen(__DIR__)))) {
+ $match[] = substr($k, 10 + strlen(__DIR__));
+ }
+ }
+ sort($match);
+
+ $this->assertSame(array('one/b/c.neon', 'one/b/d.neon'), $match);
+ }
+
+ public function testGlobToRegexDoubleStarNonStrictDots()
+ {
+ $finder = new Finder();
+ $finder->ignoreDotFiles(false);
+ $regex = Glob::toRegex('/**/*.neon', false);
+
+ foreach ($finder->in(__DIR__) as $k => $v) {
+ $k = str_replace(DIRECTORY_SEPARATOR, '/', $k);
+ if (preg_match($regex, substr($k, strlen(__DIR__)))) {
+ $match[] = substr($k, 10 + strlen(__DIR__));
+ }
+ }
+ sort($match);
+
+ $this->assertSame(array('.dot/b/c.neon', '.dot/b/d.neon', 'one/b/c.neon', 'one/b/d.neon'), $match);
+ }
+
+ public function testGlobToRegexDoubleStarWithoutLeadingSlash()
+ {
+ $finder = new Finder();
+ $finder->ignoreDotFiles(false);
+ $regex = Glob::toRegex('/Fixtures/one/**');
+
+ foreach ($finder->in(__DIR__) as $k => $v) {
+ $k = str_replace(DIRECTORY_SEPARATOR, '/', $k);
+ if (preg_match($regex, substr($k, strlen(__DIR__)))) {
+ $match[] = substr($k, 10 + strlen(__DIR__));
+ }
+ }
+ sort($match);
+
+ $this->assertSame(array('one/a', 'one/b', 'one/b/c.neon', 'one/b/d.neon'), $match);
+ }
+
+ public function testGlobToRegexDoubleStarWithoutLeadingSlashNotStrictLeadingDot()
+ {
+ $finder = new Finder();
+ $finder->ignoreDotFiles(false);
+ $regex = Glob::toRegex('/Fixtures/one/**', false);
+
+ foreach ($finder->in(__DIR__) as $k => $v) {
+ $k = str_replace(DIRECTORY_SEPARATOR, '/', $k);
+ if (preg_match($regex, substr($k, strlen(__DIR__)))) {
+ $match[] = substr($k, 10 + strlen(__DIR__));
+ }
+ }
+ sort($match);
+
+ $this->assertSame(array('one/.dot', 'one/a', 'one/b', 'one/b/c.neon', 'one/b/d.neon'), $match);
+ }
+}
diff --git a/vendor/symfony/finder/Tests/Iterator/CustomFilterIteratorTest.php b/vendor/symfony/finder/Tests/Iterator/CustomFilterIteratorTest.php
new file mode 100644
index 00000000..b036ad13
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Iterator/CustomFilterIteratorTest.php
@@ -0,0 +1,46 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+use Symfony\Component\Finder\Iterator\CustomFilterIterator;
+
+class CustomFilterIteratorTest extends IteratorTestCase
+{
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testWithInvalidFilter()
+ {
+ new CustomFilterIterator(new Iterator(), array('foo'));
+ }
+
+ /**
+ * @dataProvider getAcceptData
+ */
+ public function testAccept($filters, $expected)
+ {
+ $inner = new Iterator(array('test.php', 'test.py', 'foo.php'));
+
+ $iterator = new CustomFilterIterator($inner, $filters);
+
+ $this->assertIterator($expected, $iterator);
+ }
+
+ public function getAcceptData()
+ {
+ return array(
+ array(array(function (\SplFileInfo $fileinfo) { return false; }), array()),
+ array(array(function (\SplFileInfo $fileinfo) { return 0 === strpos($fileinfo, 'test'); }), array('test.php', 'test.py')),
+ array(array('is_dir'), array()),
+ );
+ }
+}
diff --git a/vendor/symfony/finder/Tests/Iterator/DateRangeFilterIteratorTest.php b/vendor/symfony/finder/Tests/Iterator/DateRangeFilterIteratorTest.php
new file mode 100644
index 00000000..1ec70518
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Iterator/DateRangeFilterIteratorTest.php
@@ -0,0 +1,74 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+use Symfony\Component\Finder\Iterator\DateRangeFilterIterator;
+use Symfony\Component\Finder\Comparator\DateComparator;
+
+class DateRangeFilterIteratorTest extends RealIteratorTestCase
+{
+ /**
+ * @dataProvider getAcceptData
+ */
+ public function testAccept($size, $expected)
+ {
+ $files = self::$files;
+ $files[] = self::toAbsolute('doesnotexist');
+ $inner = new Iterator($files);
+
+ $iterator = new DateRangeFilterIterator($inner, $size);
+
+ $this->assertIterator($expected, $iterator);
+ }
+
+ public function getAcceptData()
+ {
+ $since20YearsAgo = array(
+ '.git',
+ 'test.py',
+ 'foo',
+ 'foo/bar.tmp',
+ 'test.php',
+ 'toto',
+ 'toto/.git',
+ '.bar',
+ '.foo',
+ '.foo/.bar',
+ 'foo bar',
+ '.foo/bar',
+ );
+
+ $since2MonthsAgo = array(
+ '.git',
+ 'test.py',
+ 'foo',
+ 'toto',
+ 'toto/.git',
+ '.bar',
+ '.foo',
+ '.foo/.bar',
+ 'foo bar',
+ '.foo/bar',
+ );
+
+ $untilLastMonth = array(
+ 'foo/bar.tmp',
+ 'test.php',
+ );
+
+ return array(
+ array(array(new DateComparator('since 20 years ago')), $this->toAbsolute($since20YearsAgo)),
+ array(array(new DateComparator('since 2 months ago')), $this->toAbsolute($since2MonthsAgo)),
+ array(array(new DateComparator('until last month')), $this->toAbsolute($untilLastMonth)),
+ );
+ }
+}
diff --git a/vendor/symfony/finder/Tests/Iterator/DepthRangeFilterIteratorTest.php b/vendor/symfony/finder/Tests/Iterator/DepthRangeFilterIteratorTest.php
new file mode 100644
index 00000000..2e901405
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Iterator/DepthRangeFilterIteratorTest.php
@@ -0,0 +1,83 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+use Symfony\Component\Finder\Iterator\DepthRangeFilterIterator;
+
+class DepthRangeFilterIteratorTest extends RealIteratorTestCase
+{
+ /**
+ * @dataProvider getAcceptData
+ */
+ public function testAccept($minDepth, $maxDepth, $expected)
+ {
+ $inner = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->toAbsolute(), \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST);
+
+ $iterator = new DepthRangeFilterIterator($inner, $minDepth, $maxDepth);
+
+ $actual = array_keys(iterator_to_array($iterator));
+ sort($expected);
+ sort($actual);
+ $this->assertEquals($expected, $actual);
+ }
+
+ public function getAcceptData()
+ {
+ $lessThan1 = array(
+ '.git',
+ 'test.py',
+ 'foo',
+ 'test.php',
+ 'toto',
+ '.foo',
+ '.bar',
+ 'foo bar',
+ );
+
+ $lessThanOrEqualTo1 = array(
+ '.git',
+ 'test.py',
+ 'foo',
+ 'foo/bar.tmp',
+ 'test.php',
+ 'toto',
+ 'toto/.git',
+ '.foo',
+ '.foo/.bar',
+ '.bar',
+ 'foo bar',
+ '.foo/bar',
+ );
+
+ $graterThanOrEqualTo1 = array(
+ 'toto/.git',
+ 'foo/bar.tmp',
+ '.foo/.bar',
+ '.foo/bar',
+ );
+
+ $equalTo1 = array(
+ 'toto/.git',
+ 'foo/bar.tmp',
+ '.foo/.bar',
+ '.foo/bar',
+ );
+
+ return array(
+ array(0, 0, $this->toAbsolute($lessThan1)),
+ array(0, 1, $this->toAbsolute($lessThanOrEqualTo1)),
+ array(2, PHP_INT_MAX, array()),
+ array(1, PHP_INT_MAX, $this->toAbsolute($graterThanOrEqualTo1)),
+ array(1, 1, $this->toAbsolute($equalTo1)),
+ );
+ }
+}
diff --git a/vendor/symfony/finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.php b/vendor/symfony/finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.php
new file mode 100644
index 00000000..fa192c31
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.php
@@ -0,0 +1,80 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+use Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator;
+use Symfony\Component\Finder\Iterator\RecursiveDirectoryIterator;
+
+class ExcludeDirectoryFilterIteratorTest extends RealIteratorTestCase
+{
+ /**
+ * @dataProvider getAcceptData
+ */
+ public function testAccept($directories, $expected)
+ {
+ $inner = new \RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->toAbsolute(), \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST);
+
+ $iterator = new ExcludeDirectoryFilterIterator($inner, $directories);
+
+ $this->assertIterator($expected, $iterator);
+ }
+
+ public function getAcceptData()
+ {
+ $foo = array(
+ '.bar',
+ '.foo',
+ '.foo/.bar',
+ '.foo/bar',
+ '.git',
+ 'test.py',
+ 'test.php',
+ 'toto',
+ 'toto/.git',
+ 'foo bar',
+ );
+
+ $fo = array(
+ '.bar',
+ '.foo',
+ '.foo/.bar',
+ '.foo/bar',
+ '.git',
+ 'test.py',
+ 'foo',
+ 'foo/bar.tmp',
+ 'test.php',
+ 'toto',
+ 'toto/.git',
+ 'foo bar',
+ );
+
+ $toto = array(
+ '.bar',
+ '.foo',
+ '.foo/.bar',
+ '.foo/bar',
+ '.git',
+ 'test.py',
+ 'foo',
+ 'foo/bar.tmp',
+ 'test.php',
+ 'foo bar',
+ );
+
+ return array(
+ array(array('foo'), $this->toAbsolute($foo)),
+ array(array('fo'), $this->toAbsolute($fo)),
+ array(array('toto/'), $this->toAbsolute($toto)),
+ );
+ }
+}
diff --git a/vendor/symfony/finder/Tests/Iterator/FileTypeFilterIteratorTest.php b/vendor/symfony/finder/Tests/Iterator/FileTypeFilterIteratorTest.php
new file mode 100644
index 00000000..4350b00c
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Iterator/FileTypeFilterIteratorTest.php
@@ -0,0 +1,73 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+use Symfony\Component\Finder\Iterator\FileTypeFilterIterator;
+
+class FileTypeFilterIteratorTest extends RealIteratorTestCase
+{
+ /**
+ * @dataProvider getAcceptData
+ */
+ public function testAccept($mode, $expected)
+ {
+ $inner = new InnerTypeIterator(self::$files);
+
+ $iterator = new FileTypeFilterIterator($inner, $mode);
+
+ $this->assertIterator($expected, $iterator);
+ }
+
+ public function getAcceptData()
+ {
+ $onlyFiles = array(
+ 'test.py',
+ 'foo/bar.tmp',
+ 'test.php',
+ '.bar',
+ '.foo/.bar',
+ '.foo/bar',
+ 'foo bar',
+ );
+
+ $onlyDirectories = array(
+ '.git',
+ 'foo',
+ 'toto',
+ 'toto/.git',
+ '.foo',
+ );
+
+ return array(
+ array(FileTypeFilterIterator::ONLY_FILES, $this->toAbsolute($onlyFiles)),
+ array(FileTypeFilterIterator::ONLY_DIRECTORIES, $this->toAbsolute($onlyDirectories)),
+ );
+ }
+}
+
+class InnerTypeIterator extends \ArrayIterator
+{
+ public function current()
+ {
+ return new \SplFileInfo(parent::current());
+ }
+
+ public function isFile()
+ {
+ return $this->current()->isFile();
+ }
+
+ public function isDir()
+ {
+ return $this->current()->isDir();
+ }
+}
diff --git a/vendor/symfony/finder/Tests/Iterator/FilecontentFilterIteratorTest.php b/vendor/symfony/finder/Tests/Iterator/FilecontentFilterIteratorTest.php
new file mode 100644
index 00000000..744bdae1
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Iterator/FilecontentFilterIteratorTest.php
@@ -0,0 +1,86 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+use Symfony\Component\Finder\Iterator\FilecontentFilterIterator;
+
+class FilecontentFilterIteratorTest extends IteratorTestCase
+{
+ public function testAccept()
+ {
+ $inner = new MockFileListIterator(array('test.txt'));
+ $iterator = new FilecontentFilterIterator($inner, array(), array());
+ $this->assertIterator(array('test.txt'), $iterator);
+ }
+
+ public function testDirectory()
+ {
+ $inner = new MockFileListIterator(array('directory'));
+ $iterator = new FilecontentFilterIterator($inner, array('directory'), array());
+ $this->assertIterator(array(), $iterator);
+ }
+
+ public function testUnreadableFile()
+ {
+ $inner = new MockFileListIterator(array('file r-'));
+ $iterator = new FilecontentFilterIterator($inner, array('file r-'), array());
+ $this->assertIterator(array(), $iterator);
+ }
+
+ /**
+ * @dataProvider getTestFilterData
+ */
+ public function testFilter(\Iterator $inner, array $matchPatterns, array $noMatchPatterns, array $resultArray)
+ {
+ $iterator = new FilecontentFilterIterator($inner, $matchPatterns, $noMatchPatterns);
+ $this->assertIterator($resultArray, $iterator);
+ }
+
+ public function getTestFilterData()
+ {
+ $inner = new MockFileListIterator();
+
+ $inner[] = new MockSplFileInfo(array(
+ 'name' => 'a.txt',
+ 'contents' => 'Lorem ipsum...',
+ 'type' => 'file',
+ 'mode' => 'r+', )
+ );
+
+ $inner[] = new MockSplFileInfo(array(
+ 'name' => 'b.yml',
+ 'contents' => 'dolor sit...',
+ 'type' => 'file',
+ 'mode' => 'r+', )
+ );
+
+ $inner[] = new MockSplFileInfo(array(
+ 'name' => 'some/other/dir/third.php',
+ 'contents' => 'amet...',
+ 'type' => 'file',
+ 'mode' => 'r+', )
+ );
+
+ $inner[] = new MockSplFileInfo(array(
+ 'name' => 'unreadable-file.txt',
+ 'contents' => false,
+ 'type' => 'file',
+ 'mode' => 'r+', )
+ );
+
+ return array(
+ array($inner, array('.'), array(), array('a.txt', 'b.yml', 'some/other/dir/third.php')),
+ array($inner, array('ipsum'), array(), array('a.txt')),
+ array($inner, array('i', 'amet'), array('Lorem', 'amet'), array('b.yml')),
+ );
+ }
+}
diff --git a/vendor/symfony/finder/Tests/Iterator/FilenameFilterIteratorTest.php b/vendor/symfony/finder/Tests/Iterator/FilenameFilterIteratorTest.php
new file mode 100644
index 00000000..c4b97959
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Iterator/FilenameFilterIteratorTest.php
@@ -0,0 +1,54 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+use Symfony\Component\Finder\Iterator\FilenameFilterIterator;
+
+class FilenameFilterIteratorTest extends IteratorTestCase
+{
+ /**
+ * @dataProvider getAcceptData
+ */
+ public function testAccept($matchPatterns, $noMatchPatterns, $expected)
+ {
+ $inner = new InnerNameIterator(array('test.php', 'test.py', 'foo.php'));
+
+ $iterator = new FilenameFilterIterator($inner, $matchPatterns, $noMatchPatterns);
+
+ $this->assertIterator($expected, $iterator);
+ }
+
+ public function getAcceptData()
+ {
+ return array(
+ array(array('test.*'), array(), array('test.php', 'test.py')),
+ array(array(), array('test.*'), array('foo.php')),
+ array(array('*.php'), array('test.*'), array('foo.php')),
+ array(array('*.php', '*.py'), array('foo.*'), array('test.php', 'test.py')),
+ array(array('/\.php$/'), array(), array('test.php', 'foo.php')),
+ array(array(), array('/\.php$/'), array('test.py')),
+ );
+ }
+}
+
+class InnerNameIterator extends \ArrayIterator
+{
+ public function current()
+ {
+ return new \SplFileInfo(parent::current());
+ }
+
+ public function getFilename()
+ {
+ return parent::current();
+ }
+}
diff --git a/vendor/symfony/finder/Tests/Iterator/FilterIteratorTest.php b/vendor/symfony/finder/Tests/Iterator/FilterIteratorTest.php
new file mode 100644
index 00000000..8b1a4482
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Iterator/FilterIteratorTest.php
@@ -0,0 +1,53 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+/**
+ * @author Alex Bogomazov
+ *
+ * @group legacy
+ */
+class FilterIteratorTest extends RealIteratorTestCase
+{
+ public function testFilterFilesystemIterators()
+ {
+ $i = new \FilesystemIterator($this->toAbsolute());
+
+ // it is expected that there are test.py test.php in the tmpDir
+ $i = $this->getMockForAbstractClass('Symfony\Component\Finder\Iterator\FilterIterator', array($i));
+ $i->expects($this->any())
+ ->method('accept')
+ ->will($this->returnCallback(function () use ($i) {
+ return (bool) preg_match('/\.php/', (string) $i->current());
+ })
+ );
+
+ $c = 0;
+ foreach ($i as $item) {
+ ++$c;
+ }
+
+ $this->assertEquals(1, $c);
+
+ $i->rewind();
+
+ $c = 0;
+ foreach ($i as $item) {
+ ++$c;
+ }
+
+ // This would fail in php older than 5.5.23/5.6.7 with \FilterIterator
+ // but works with Symfony\Component\Finder\Iterator\FilterIterator
+ // see https://bugs.php.net/68557
+ $this->assertEquals(1, $c);
+ }
+}
diff --git a/vendor/symfony/finder/Tests/Iterator/Iterator.php b/vendor/symfony/finder/Tests/Iterator/Iterator.php
new file mode 100644
index 00000000..849bf081
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Iterator/Iterator.php
@@ -0,0 +1,55 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+class Iterator implements \Iterator
+{
+ protected $values = array();
+
+ public function __construct(array $values = array())
+ {
+ foreach ($values as $value) {
+ $this->attach(new \SplFileInfo($value));
+ }
+ $this->rewind();
+ }
+
+ public function attach(\SplFileInfo $fileinfo)
+ {
+ $this->values[] = $fileinfo;
+ }
+
+ public function rewind()
+ {
+ reset($this->values);
+ }
+
+ public function valid()
+ {
+ return false !== $this->current();
+ }
+
+ public function next()
+ {
+ next($this->values);
+ }
+
+ public function current()
+ {
+ return current($this->values);
+ }
+
+ public function key()
+ {
+ return key($this->values);
+ }
+}
diff --git a/vendor/symfony/finder/Tests/Iterator/IteratorTestCase.php b/vendor/symfony/finder/Tests/Iterator/IteratorTestCase.php
new file mode 100644
index 00000000..c724a75c
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Iterator/IteratorTestCase.php
@@ -0,0 +1,100 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+use PHPUnit\Framework\TestCase;
+
+abstract class IteratorTestCase extends TestCase
+{
+ protected function assertIterator($expected, \Traversable $iterator)
+ {
+ // set iterator_to_array $use_key to false to avoid values merge
+ // this made FinderTest::testAppendWithAnArray() fail with GnuFinderAdapter
+ $values = array_map(function (\SplFileInfo $fileinfo) { return str_replace('/', DIRECTORY_SEPARATOR, $fileinfo->getPathname()); }, iterator_to_array($iterator, false));
+
+ $expected = array_map(function ($path) { return str_replace('/', DIRECTORY_SEPARATOR, $path); }, $expected);
+
+ sort($values);
+ sort($expected);
+
+ $this->assertEquals($expected, array_values($values));
+ }
+
+ protected function assertOrderedIterator($expected, \Traversable $iterator)
+ {
+ $values = array_map(function (\SplFileInfo $fileinfo) { return $fileinfo->getPathname(); }, iterator_to_array($iterator));
+
+ $this->assertEquals($expected, array_values($values));
+ }
+
+ /**
+ * Same as assertOrderedIterator, but checks the order of groups of
+ * array elements.
+ *
+ * @param array $expected - an array of arrays. For any two subarrays
+ * $a and $b such that $a goes before $b in $expected, the method
+ * asserts that any element of $a goes before any element of $b
+ * in the sequence generated by $iterator
+ * @param \Traversable $iterator
+ */
+ protected function assertOrderedIteratorForGroups($expected, \Traversable $iterator)
+ {
+ $values = array_values(array_map(function (\SplFileInfo $fileinfo) { return $fileinfo->getPathname(); }, iterator_to_array($iterator)));
+
+ foreach ($expected as $subarray) {
+ $temp = array();
+ while (count($values) && count($temp) < count($subarray)) {
+ $temp[] = array_shift($values);
+ }
+ sort($temp);
+ sort($subarray);
+ $this->assertEquals($subarray, $temp);
+ }
+ }
+
+ /**
+ * Same as IteratorTestCase::assertIterator with foreach usage.
+ *
+ * @param array $expected
+ * @param \Traversable $iterator
+ */
+ protected function assertIteratorInForeach($expected, \Traversable $iterator)
+ {
+ $values = array();
+ foreach ($iterator as $file) {
+ $this->assertInstanceOf('Symfony\\Component\\Finder\\SplFileInfo', $file);
+ $values[] = $file->getPathname();
+ }
+
+ sort($values);
+ sort($expected);
+
+ $this->assertEquals($expected, array_values($values));
+ }
+
+ /**
+ * Same as IteratorTestCase::assertOrderedIterator with foreach usage.
+ *
+ * @param array $expected
+ * @param \Traversable $iterator
+ */
+ protected function assertOrderedIteratorInForeach($expected, \Traversable $iterator)
+ {
+ $values = array();
+ foreach ($iterator as $file) {
+ $this->assertInstanceOf('Symfony\\Component\\Finder\\SplFileInfo', $file);
+ $values[] = $file->getPathname();
+ }
+
+ $this->assertEquals($expected, array_values($values));
+ }
+}
diff --git a/vendor/symfony/finder/Tests/Iterator/MockFileListIterator.php b/vendor/symfony/finder/Tests/Iterator/MockFileListIterator.php
new file mode 100644
index 00000000..eb0adfad
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Iterator/MockFileListIterator.php
@@ -0,0 +1,21 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+class MockFileListIterator extends \ArrayIterator
+{
+ public function __construct(array $filesArray = array())
+ {
+ $files = array_map(function ($file) { return new MockSplFileInfo($file); }, $filesArray);
+ parent::__construct($files);
+ }
+}
diff --git a/vendor/symfony/finder/Tests/Iterator/MockSplFileInfo.php b/vendor/symfony/finder/Tests/Iterator/MockSplFileInfo.php
new file mode 100644
index 00000000..cfe31c90
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Iterator/MockSplFileInfo.php
@@ -0,0 +1,132 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+class MockSplFileInfo extends \SplFileInfo
+{
+ const TYPE_DIRECTORY = 1;
+ const TYPE_FILE = 2;
+ const TYPE_UNKNOWN = 3;
+
+ private $contents = null;
+ private $mode = null;
+ private $type = null;
+ private $relativePath = null;
+ private $relativePathname = null;
+
+ public function __construct($param)
+ {
+ if (is_string($param)) {
+ parent::__construct($param);
+ } elseif (is_array($param)) {
+ $defaults = array(
+ 'name' => 'file.txt',
+ 'contents' => null,
+ 'mode' => null,
+ 'type' => null,
+ 'relativePath' => null,
+ 'relativePathname' => null,
+ );
+ $defaults = array_merge($defaults, $param);
+ parent::__construct($defaults['name']);
+ $this->setContents($defaults['contents']);
+ $this->setMode($defaults['mode']);
+ $this->setType($defaults['type']);
+ $this->setRelativePath($defaults['relativePath']);
+ $this->setRelativePathname($defaults['relativePathname']);
+ } else {
+ throw new \RuntimeException(sprintf('Incorrect parameter "%s"', $param));
+ }
+ }
+
+ public function isFile()
+ {
+ if (null === $this->type) {
+ return false !== strpos($this->getFilename(), 'file');
+ }
+
+ return self::TYPE_FILE === $this->type;
+ }
+
+ public function isDir()
+ {
+ if (null === $this->type) {
+ return false !== strpos($this->getFilename(), 'directory');
+ }
+
+ return self::TYPE_DIRECTORY === $this->type;
+ }
+
+ public function isReadable()
+ {
+ if (null === $this->mode) {
+ return preg_match('/r\+/', $this->getFilename());
+ }
+
+ return preg_match('/r\+/', $this->mode);
+ }
+
+ public function getContents()
+ {
+ return $this->contents;
+ }
+
+ public function setContents($contents)
+ {
+ $this->contents = $contents;
+ }
+
+ public function setMode($mode)
+ {
+ $this->mode = $mode;
+ }
+
+ public function setType($type)
+ {
+ if (is_string($type)) {
+ switch ($type) {
+ case 'directory':
+ case 'd':
+ $this->type = self::TYPE_DIRECTORY;
+ break;
+ case 'file':
+ case 'f':
+ $this->type = self::TYPE_FILE;
+ break;
+ default:
+ $this->type = self::TYPE_UNKNOWN;
+ }
+ } else {
+ $this->type = $type;
+ }
+ }
+
+ public function setRelativePath($relativePath)
+ {
+ $this->relativePath = $relativePath;
+ }
+
+ public function setRelativePathname($relativePathname)
+ {
+ $this->relativePathname = $relativePathname;
+ }
+
+ public function getRelativePath()
+ {
+ return $this->relativePath;
+ }
+
+ public function getRelativePathname()
+ {
+ return $this->relativePathname;
+ }
+}
diff --git a/vendor/symfony/finder/Tests/Iterator/MultiplePcreFilterIteratorTest.php b/vendor/symfony/finder/Tests/Iterator/MultiplePcreFilterIteratorTest.php
new file mode 100644
index 00000000..f2c1cd24
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Iterator/MultiplePcreFilterIteratorTest.php
@@ -0,0 +1,71 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Finder\Iterator\MultiplePcreFilterIterator;
+
+class MultiplePcreFilterIteratorTest extends TestCase
+{
+ /**
+ * @dataProvider getIsRegexFixtures
+ */
+ public function testIsRegex($string, $isRegex, $message)
+ {
+ $testIterator = new TestMultiplePcreFilterIterator();
+ $this->assertEquals($isRegex, $testIterator->isRegex($string), $message);
+ }
+
+ public function getIsRegexFixtures()
+ {
+ return array(
+ array('foo', false, 'string'),
+ array(' foo ', false, '" " is not a valid delimiter'),
+ array('\\foo\\', false, '"\\" is not a valid delimiter'),
+ array('afooa', false, '"a" is not a valid delimiter'),
+ array('//', false, 'the pattern should contain at least 1 character'),
+ array('/a/', true, 'valid regex'),
+ array('/foo/', true, 'valid regex'),
+ array('/foo/i', true, 'valid regex with a single modifier'),
+ array('/foo/imsxu', true, 'valid regex with multiple modifiers'),
+ array('#foo#', true, '"#" is a valid delimiter'),
+ array('{foo}', true, '"{,}" is a valid delimiter pair'),
+ array('[foo]', true, '"[,]" is a valid delimiter pair'),
+ array('(foo)', true, '"(,)" is a valid delimiter pair'),
+ array('<foo>', true, '"<,>" is a valid delimiter pair'),
+ array('*foo.*', false, '"*" is not considered as a valid delimiter'),
+ array('?foo.?', false, '"?" is not considered as a valid delimiter'),
+ );
+ }
+}
+
+class TestMultiplePcreFilterIterator extends MultiplePcreFilterIterator
+{
+ public function __construct()
+ {
+ }
+
+ public function accept()
+ {
+ throw new \BadFunctionCallException('Not implemented');
+ }
+
+ public function isRegex($str)
+ {
+ return parent::isRegex($str);
+ }
+
+ public function toRegex($str)
+ {
+ throw new \BadFunctionCallException('Not implemented');
+ }
+}
diff --git a/vendor/symfony/finder/Tests/Iterator/PathFilterIteratorTest.php b/vendor/symfony/finder/Tests/Iterator/PathFilterIteratorTest.php
new file mode 100644
index 00000000..6e10550c
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Iterator/PathFilterIteratorTest.php
@@ -0,0 +1,82 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+use Symfony\Component\Finder\Iterator\PathFilterIterator;
+
+class PathFilterIteratorTest extends IteratorTestCase
+{
+ /**
+ * @dataProvider getTestFilterData
+ */
+ public function testFilter(\Iterator $inner, array $matchPatterns, array $noMatchPatterns, array $resultArray)
+ {
+ $iterator = new PathFilterIterator($inner, $matchPatterns, $noMatchPatterns);
+ $this->assertIterator($resultArray, $iterator);
+ }
+
+ public function getTestFilterData()
+ {
+ $inner = new MockFileListIterator();
+
+ //PATH: A/B/C/abc.dat
+ $inner[] = new MockSplFileInfo(array(
+ 'name' => 'abc.dat',
+ 'relativePathname' => 'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat',
+ ));
+
+ //PATH: A/B/ab.dat
+ $inner[] = new MockSplFileInfo(array(
+ 'name' => 'ab.dat',
+ 'relativePathname' => 'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'ab.dat',
+ ));
+
+ //PATH: A/a.dat
+ $inner[] = new MockSplFileInfo(array(
+ 'name' => 'a.dat',
+ 'relativePathname' => 'A'.DIRECTORY_SEPARATOR.'a.dat',
+ ));
+
+ //PATH: copy/A/B/C/abc.dat.copy
+ $inner[] = new MockSplFileInfo(array(
+ 'name' => 'abc.dat.copy',
+ 'relativePathname' => 'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat',
+ ));
+
+ //PATH: copy/A/B/ab.dat.copy
+ $inner[] = new MockSplFileInfo(array(
+ 'name' => 'ab.dat.copy',
+ 'relativePathname' => 'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'ab.dat',
+ ));
+
+ //PATH: copy/A/a.dat.copy
+ $inner[] = new MockSplFileInfo(array(
+ 'name' => 'a.dat.copy',
+ 'relativePathname' => 'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'a.dat',
+ ));
+
+ return array(
+ array($inner, array('/^A/'), array(), array('abc.dat', 'ab.dat', 'a.dat')),
+ array($inner, array('/^A\/B/'), array(), array('abc.dat', 'ab.dat')),
+ array($inner, array('/^A\/B\/C/'), array(), array('abc.dat')),
+ array($inner, array('/A\/B\/C/'), array(), array('abc.dat', 'abc.dat.copy')),
+
+ array($inner, array('A'), array(), array('abc.dat', 'ab.dat', 'a.dat', 'abc.dat.copy', 'ab.dat.copy', 'a.dat.copy')),
+ array($inner, array('A/B'), array(), array('abc.dat', 'ab.dat', 'abc.dat.copy', 'ab.dat.copy')),
+ array($inner, array('A/B/C'), array(), array('abc.dat', 'abc.dat.copy')),
+
+ array($inner, array('copy/A'), array(), array('abc.dat.copy', 'ab.dat.copy', 'a.dat.copy')),
+ array($inner, array('copy/A/B'), array(), array('abc.dat.copy', 'ab.dat.copy')),
+ array($inner, array('copy/A/B/C'), array(), array('abc.dat.copy')),
+ );
+ }
+}
diff --git a/vendor/symfony/finder/Tests/Iterator/RealIteratorTestCase.php b/vendor/symfony/finder/Tests/Iterator/RealIteratorTestCase.php
new file mode 100644
index 00000000..94253c7e
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Iterator/RealIteratorTestCase.php
@@ -0,0 +1,110 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+abstract class RealIteratorTestCase extends IteratorTestCase
+{
+ protected static $tmpDir;
+ protected static $files;
+
+ public static function setUpBeforeClass()
+ {
+ self::$tmpDir = realpath(sys_get_temp_dir()).DIRECTORY_SEPARATOR.'symfony_finder';
+
+ self::$files = array(
+ '.git/',
+ '.foo/',
+ '.foo/.bar',
+ '.foo/bar',
+ '.bar',
+ 'test.py',
+ 'foo/',
+ 'foo/bar.tmp',
+ 'test.php',
+ 'toto/',
+ 'toto/.git/',
+ 'foo bar',
+ );
+
+ self::$files = self::toAbsolute(self::$files);
+
+ if (is_dir(self::$tmpDir)) {
+ self::tearDownAfterClass();
+ } else {
+ mkdir(self::$tmpDir);
+ }
+
+ foreach (self::$files as $file) {
+ if (DIRECTORY_SEPARATOR === $file[strlen($file) - 1]) {
+ mkdir($file);
+ } else {
+ touch($file);
+ }
+ }
+
+ file_put_contents(self::toAbsolute('test.php'), str_repeat(' ', 800));
+ file_put_contents(self::toAbsolute('test.py'), str_repeat(' ', 2000));
+
+ touch(self::toAbsolute('foo/bar.tmp'), strtotime('2005-10-15'));
+ touch(self::toAbsolute('test.php'), strtotime('2005-10-15'));
+ }
+
+ public static function tearDownAfterClass()
+ {
+ foreach (array_reverse(self::$files) as $file) {
+ if (DIRECTORY_SEPARATOR === $file[strlen($file) - 1]) {
+ @rmdir($file);
+ } else {
+ @unlink($file);
+ }
+ }
+ }
+
+ protected static function toAbsolute($files = null)
+ {
+ /*
+ * Without the call to setUpBeforeClass() property can be null.
+ */
+ if (!self::$tmpDir) {
+ self::$tmpDir = realpath(sys_get_temp_dir()).DIRECTORY_SEPARATOR.'symfony_finder';
+ }
+
+ if (is_array($files)) {
+ $f = array();
+ foreach ($files as $file) {
+ if (is_array($file)) {
+ $f[] = self::toAbsolute($file);
+ } else {
+ $f[] = self::$tmpDir.DIRECTORY_SEPARATOR.str_replace('/', DIRECTORY_SEPARATOR, $file);
+ }
+ }
+
+ return $f;
+ }
+
+ if (is_string($files)) {
+ return self::$tmpDir.DIRECTORY_SEPARATOR.str_replace('/', DIRECTORY_SEPARATOR, $files);
+ }
+
+ return self::$tmpDir;
+ }
+
+ protected static function toAbsoluteFixtures($files)
+ {
+ $f = array();
+ foreach ($files as $file) {
+ $f[] = realpath(__DIR__.DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR.$file);
+ }
+
+ return $f;
+ }
+}
diff --git a/vendor/symfony/finder/Tests/Iterator/RecursiveDirectoryIteratorTest.php b/vendor/symfony/finder/Tests/Iterator/RecursiveDirectoryIteratorTest.php
new file mode 100644
index 00000000..3a3ddc4d
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Iterator/RecursiveDirectoryIteratorTest.php
@@ -0,0 +1,59 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+use Symfony\Component\Finder\Iterator\RecursiveDirectoryIterator;
+
+class RecursiveDirectoryIteratorTest extends IteratorTestCase
+{
+ /**
+ * @group network
+ */
+ public function testRewindOnFtp()
+ {
+ try {
+ $i = new RecursiveDirectoryIterator('ftp://speedtest.tele2.net/', \RecursiveDirectoryIterator::SKIP_DOTS);
+ } catch (\UnexpectedValueException $e) {
+ $this->markTestSkipped('Unsupported stream "ftp".');
+ }
+
+ $i->rewind();
+
+ $this->assertTrue(true);
+ }
+
+ /**
+ * @group network
+ */
+ public function testSeekOnFtp()
+ {
+ try {
+ $i = new RecursiveDirectoryIterator('ftp://speedtest.tele2.net/', \RecursiveDirectoryIterator::SKIP_DOTS);
+ } catch (\UnexpectedValueException $e) {
+ $this->markTestSkipped('Unsupported stream "ftp".');
+ }
+
+ $contains = array(
+ 'ftp://speedtest.tele2.net'.DIRECTORY_SEPARATOR.'1000GB.zip',
+ 'ftp://speedtest.tele2.net'.DIRECTORY_SEPARATOR.'100GB.zip',
+ );
+ $actual = array();
+
+ $i->seek(0);
+ $actual[] = $i->getPathname();
+
+ $i->seek(1);
+ $actual[] = $i->getPathname();
+
+ $this->assertEquals($contains, $actual);
+ }
+}
diff --git a/vendor/symfony/finder/Tests/Iterator/SizeRangeFilterIteratorTest.php b/vendor/symfony/finder/Tests/Iterator/SizeRangeFilterIteratorTest.php
new file mode 100644
index 00000000..6d75b0f2
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Iterator/SizeRangeFilterIteratorTest.php
@@ -0,0 +1,69 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+use Symfony\Component\Finder\Iterator\SizeRangeFilterIterator;
+use Symfony\Component\Finder\Comparator\NumberComparator;
+
+class SizeRangeFilterIteratorTest extends RealIteratorTestCase
+{
+ /**
+ * @dataProvider getAcceptData
+ */
+ public function testAccept($size, $expected)
+ {
+ $inner = new InnerSizeIterator(self::$files);
+
+ $iterator = new SizeRangeFilterIterator($inner, $size);
+
+ $this->assertIterator($expected, $iterator);
+ }
+
+ public function getAcceptData()
+ {
+ $lessThan1KGreaterThan05K = array(
+ '.foo',
+ '.git',
+ 'foo',
+ 'test.php',
+ 'toto',
+ 'toto/.git',
+ );
+
+ return array(
+ array(array(new NumberComparator('< 1K'), new NumberComparator('> 0.5K')), $this->toAbsolute($lessThan1KGreaterThan05K)),
+ );
+ }
+}
+
+class InnerSizeIterator extends \ArrayIterator
+{
+ public function current()
+ {
+ return new \SplFileInfo(parent::current());
+ }
+
+ public function getFilename()
+ {
+ return parent::current();
+ }
+
+ public function isFile()
+ {
+ return $this->current()->isFile();
+ }
+
+ public function getSize()
+ {
+ return $this->current()->getSize();
+ }
+}
diff --git a/vendor/symfony/finder/Tests/Iterator/SortableIteratorTest.php b/vendor/symfony/finder/Tests/Iterator/SortableIteratorTest.php
new file mode 100644
index 00000000..444654a2
--- /dev/null
+++ b/vendor/symfony/finder/Tests/Iterator/SortableIteratorTest.php
@@ -0,0 +1,183 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Finder\Tests\Iterator;
+
+use Symfony\Component\Finder\Iterator\SortableIterator;
+
+class SortableIteratorTest extends RealIteratorTestCase
+{
+ public function testConstructor()
+ {
+ try {
+ new SortableIterator(new Iterator(array()), 'foobar');
+ $this->fail('__construct() throws an \InvalidArgumentException exception if the mode is not valid');
+ } catch (\Exception $e) {
+ $this->assertInstanceOf('InvalidArgumentException', $e, '__construct() throws an \InvalidArgumentException exception if the mode is not valid');
+ }
+ }
+
+ /**
+ * @dataProvider getAcceptData
+ */
+ public function testAccept($mode, $expected)
+ {
+ if (!is_callable($mode)) {
+ switch ($mode) {
+ case SortableIterator::SORT_BY_ACCESSED_TIME:
+ if ('\\' === DIRECTORY_SEPARATOR) {
+ touch(self::toAbsolute('.git'));
+ } else {
+ file_get_contents(self::toAbsolute('.git'));
+ }
+ sleep(1);
+ file_get_contents(self::toAbsolute('.bar'));
+ break;
+ case SortableIterator::SORT_BY_CHANGED_TIME:
+ file_put_contents(self::toAbsolute('test.php'), 'foo');
+ sleep(1);
+ file_put_contents(self::toAbsolute('test.py'), 'foo');
+ break;
+ case SortableIterator::SORT_BY_MODIFIED_TIME:
+ file_put_contents(self::toAbsolute('test.php'), 'foo');
+ sleep(1);
+ file_put_contents(self::toAbsolute('test.py'), 'foo');
+ break;
+ }
+ }
+
+ $inner = new Iterator(self::$files);
+
+ $iterator = new SortableIterator($inner, $mode);
+
+ if (SortableIterator::SORT_BY_ACCESSED_TIME === $mode
+ || SortableIterator::SORT_BY_CHANGED_TIME === $mode
+ || SortableIterator::SORT_BY_MODIFIED_TIME === $mode
+ ) {
+ if ('\\' === DIRECTORY_SEPARATOR && SortableIterator::SORT_BY_MODIFIED_TIME !== $mode) {
+ $this->markTestSkipped('Sorting by atime or ctime is not supported on Windows');
+ }
+ $this->assertOrderedIteratorForGroups($expected, $iterator);
+ } else {
+ $this->assertOrderedIterator($expected, $iterator);
+ }
+ }
+
+ public function getAcceptData()
+ {
+ $sortByName = array(
+ '.bar',
+ '.foo',
+ '.foo/.bar',
+ '.foo/bar',
+ '.git',
+ 'foo',
+ 'foo bar',
+ 'foo/bar.tmp',
+ 'test.php',
+ 'test.py',
+ 'toto',
+ 'toto/.git',
+ );
+
+ $sortByType = array(
+ '.foo',
+ '.git',
+ 'foo',
+ 'toto',
+ 'toto/.git',
+ '.bar',
+ '.foo/.bar',
+ '.foo/bar',
+ 'foo bar',
+ 'foo/bar.tmp',
+ 'test.php',
+ 'test.py',
+ );
+
+ $customComparison = array(
+ '.bar',
+ '.foo',
+ '.foo/.bar',
+ '.foo/bar',
+ '.git',
+ 'foo',
+ 'foo bar',
+ 'foo/bar.tmp',
+ 'test.php',
+ 'test.py',
+ 'toto',
+ 'toto/.git',
+ );
+
+ $sortByAccessedTime = array(
+ // For these two files the access time was set to 2005-10-15
+ array('foo/bar.tmp', 'test.php'),
+ // These files were created more or less at the same time
+ array(
+ '.git',
+ '.foo',
+ '.foo/.bar',
+ '.foo/bar',
+ 'test.py',
+ 'foo',
+ 'toto',
+ 'toto/.git',
+ 'foo bar',
+ ),
+ // This file was accessed after sleeping for 1 sec
+ array('.bar'),
+ );
+
+ $sortByChangedTime = array(
+ array(
+ '.git',
+ '.foo',
+ '.foo/.bar',
+ '.foo/bar',
+ '.bar',
+ 'foo',
+ 'foo/bar.tmp',
+ 'toto',
+ 'toto/.git',
+ 'foo bar',
+ ),
+ array('test.php'),
+ array('test.py'),
+ );
+
+ $sortByModifiedTime = array(
+ array(
+ '.git',
+ '.foo',
+ '.foo/.bar',
+ '.foo/bar',
+ '.bar',
+ 'foo',
+ 'foo/bar.tmp',
+ 'toto',
+ 'toto/.git',
+ 'foo bar',
+ ),
+ array('test.php'),
+ array('test.py'),
+ );
+
+ return array(
+ array(SortableIterator::SORT_BY_NAME, $this->toAbsolute($sortByName)),
+ array(SortableIterator::SORT_BY_TYPE, $this->toAbsolute($sortByType)),
+ array(SortableIterator::SORT_BY_ACCESSED_TIME, $this->toAbsolute($sortByAccessedTime)),
+ array(SortableIterator::SORT_BY_CHANGED_TIME, $this->toAbsolute($sortByChangedTime)),
+ array(SortableIterator::SORT_BY_MODIFIED_TIME, $this->toAbsolute($sortByModifiedTime)),
+ array(function (\SplFileInfo $a, \SplFileInfo $b) { return strcmp($a->getRealPath(), $b->getRealPath()); }, $this->toAbsolute($customComparison)),
+ );
+ }
+}
diff --git a/vendor/symfony/finder/composer.json b/vendor/symfony/finder/composer.json
new file mode 100644
index 00000000..de19826f
--- /dev/null
+++ b/vendor/symfony/finder/composer.json
@@ -0,0 +1,33 @@
+{
+ "name": "symfony/finder",
+ "type": "library",
+ "description": "Symfony Finder Component",
+ "keywords": [],
+ "homepage": "https://symfony.com",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": "^5.5.9|>=7.0.8"
+ },
+ "autoload": {
+ "psr-4": { "Symfony\\Component\\Finder\\": "" },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "minimum-stability": "dev",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.4-dev"
+ }
+ }
+}
diff --git a/vendor/symfony/finder/phpunit.xml.dist b/vendor/symfony/finder/phpunit.xml.dist
new file mode 100644
index 00000000..0e1a8669
--- /dev/null
+++ b/vendor/symfony/finder/phpunit.xml.dist
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
+ backupGlobals="false"
+ colors="true"
+ bootstrap="vendor/autoload.php"
+ failOnRisky="true"
+ failOnWarning="true"
+>
+ <php>
+ <ini name="error_reporting" value="-1" />
+ </php>
+
+ <testsuites>
+ <testsuite name="Symfony Finder Component Test Suite">
+ <directory>./Tests/</directory>
+ </testsuite>
+ </testsuites>
+
+ <filter>
+ <whitelist>
+ <directory>./</directory>
+ <exclude>
+ <directory>./Tests</directory>
+ <directory>./vendor</directory>
+ </exclude>
+ </whitelist>
+ </filter>
+</phpunit>