parent
cfac24c461
commit
a7b84c53dc
File diff suppressed because it is too large
Load Diff
@ -1 +1 @@ |
||||
Subproject commit 869aa9edba10d86c16a59384f523de96343f9944 |
||||
Subproject commit a19e61708a014d7cb7edad62effe90dd37700282 |
||||
@ -1,4 +0,0 @@ |
||||
vendor/ |
||||
composer.lock |
||||
phpunit.xml |
||||
|
||||
@ -1,225 +0,0 @@ |
||||
<?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\Adapter; |
||||
|
||||
/** |
||||
* Interface for finder engine implementations. |
||||
* |
||||
* @author Jean-François Simon <contact@jfsimon.fr> |
||||
*/ |
||||
abstract class AbstractAdapter implements AdapterInterface |
||||
{ |
||||
protected $followLinks = false; |
||||
protected $mode = 0; |
||||
protected $minDepth = 0; |
||||
protected $maxDepth = INF; |
||||
protected $exclude = array(); |
||||
protected $names = array(); |
||||
protected $notNames = array(); |
||||
protected $contains = array(); |
||||
protected $notContains = array(); |
||||
protected $sizes = array(); |
||||
protected $dates = array(); |
||||
protected $filters = array(); |
||||
protected $sort = false; |
||||
protected $paths = array(); |
||||
protected $notPaths = array(); |
||||
|
||||
private static $areSupported = array(); |
||||
|
||||
/** |
||||
* {@inheritDoc} |
||||
*/ |
||||
public function isSupported() |
||||
{ |
||||
$name = $this->getName(); |
||||
|
||||
if (!array_key_exists($name, self::$areSupported)) { |
||||
self::$areSupported[$name] = $this->canBeUsed(); |
||||
} |
||||
|
||||
return self::$areSupported[$name]; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function setFollowLinks($followLinks) |
||||
{ |
||||
$this->followLinks = $followLinks; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function setMode($mode) |
||||
{ |
||||
$this->mode = $mode; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function setDepths(array $depths) |
||||
{ |
||||
$this->minDepth = 0; |
||||
$this->maxDepth = INF; |
||||
|
||||
foreach ($depths as $comparator) { |
||||
switch ($comparator->getOperator()) { |
||||
case '>': |
||||
$this->minDepth = $comparator->getTarget() + 1; |
||||
break; |
||||
case '>=': |
||||
$this->minDepth = $comparator->getTarget(); |
||||
break; |
||||
case '<': |
||||
$this->maxDepth = $comparator->getTarget() - 1; |
||||
break; |
||||
case '<=': |
||||
$this->maxDepth = $comparator->getTarget(); |
||||
break; |
||||
default: |
||||
$this->minDepth = $this->maxDepth = $comparator->getTarget(); |
||||
} |
||||
} |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function setExclude(array $exclude) |
||||
{ |
||||
$this->exclude = $exclude; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function setNames(array $names) |
||||
{ |
||||
$this->names = $names; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function setNotNames(array $notNames) |
||||
{ |
||||
$this->notNames = $notNames; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function setContains(array $contains) |
||||
{ |
||||
$this->contains = $contains; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function setNotContains(array $notContains) |
||||
{ |
||||
$this->notContains = $notContains; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function setSizes(array $sizes) |
||||
{ |
||||
$this->sizes = $sizes; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function setDates(array $dates) |
||||
{ |
||||
$this->dates = $dates; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function setFilters(array $filters) |
||||
{ |
||||
$this->filters = $filters; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function setSort($sort) |
||||
{ |
||||
$this->sort = $sort; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function setPath(array $paths) |
||||
{ |
||||
$this->paths = $paths; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function setNotPath(array $notPaths) |
||||
{ |
||||
$this->notPaths = $notPaths; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* Returns whether the adapter is supported in the current environment. |
||||
* |
||||
* This method should be implemented in all adapters. Do not implement |
||||
* isSupported in the adapters as the generic implementation provides a cache |
||||
* layer. |
||||
* |
||||
* @see isSupported |
||||
* |
||||
* @return Boolean Whether the adapter is supported |
||||
*/ |
||||
abstract protected function canBeUsed(); |
||||
} |
||||
@ -1,320 +0,0 @@ |
||||
<?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\Adapter; |
||||
|
||||
use Symfony\Component\Finder\Iterator; |
||||
use Symfony\Component\Finder\Shell\Shell; |
||||
use Symfony\Component\Finder\Expression\Expression; |
||||
use Symfony\Component\Finder\Shell\Command; |
||||
use Symfony\Component\Finder\Iterator\SortableIterator; |
||||
use Symfony\Component\Finder\Comparator\NumberComparator; |
||||
use Symfony\Component\Finder\Comparator\DateComparator; |
||||
|
||||
/** |
||||
* Shell engine implementation using GNU find command. |
||||
* |
||||
* @author Jean-François Simon <contact@jfsimon.fr> |
||||
*/ |
||||
abstract class AbstractFindAdapter extends AbstractAdapter |
||||
{ |
||||
/** |
||||
* @var Shell |
||||
*/ |
||||
protected $shell; |
||||
|
||||
/** |
||||
* Constructor. |
||||
*/ |
||||
public function __construct() |
||||
{ |
||||
$this->shell = new Shell(); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function searchInDirectory($dir) |
||||
{ |
||||
// having "/../" in path make find fail |
||||
$dir = realpath($dir); |
||||
|
||||
// searching directories containing or not containing strings leads to no result |
||||
if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode && ($this->contains || $this->notContains)) { |
||||
return new Iterator\FilePathsIterator(array(), $dir); |
||||
} |
||||
|
||||
$command = Command::create(); |
||||
$find = $this->buildFindCommand($command, $dir); |
||||
|
||||
if ($this->followLinks) { |
||||
$find->add('-follow'); |
||||
} |
||||
|
||||
$find->add('-mindepth')->add($this->minDepth + 1); |
||||
// warning! INF < INF => true ; INF == INF => false ; INF === INF => true |
||||
// https://bugs.php.net/bug.php?id=9118 |
||||
if (INF !== $this->maxDepth) { |
||||
$find->add('-maxdepth')->add($this->maxDepth + 1); |
||||
} |
||||
|
||||
if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode) { |
||||
$find->add('-type d'); |
||||
} elseif (Iterator\FileTypeFilterIterator::ONLY_FILES === $this->mode) { |
||||
$find->add('-type f'); |
||||
} |
||||
|
||||
$this->buildNamesFiltering($find, $this->names); |
||||
$this->buildNamesFiltering($find, $this->notNames, true); |
||||
$this->buildPathsFiltering($find, $dir, $this->paths); |
||||
$this->buildPathsFiltering($find, $dir, $this->notPaths, true); |
||||
$this->buildSizesFiltering($find, $this->sizes); |
||||
$this->buildDatesFiltering($find, $this->dates); |
||||
|
||||
$useGrep = $this->shell->testCommand('grep') && $this->shell->testCommand('xargs'); |
||||
$useSort = is_int($this->sort) && $this->shell->testCommand('sort') && $this->shell->testCommand('cut'); |
||||
|
||||
if ($useGrep && ($this->contains || $this->notContains)) { |
||||
$grep = $command->ins('grep'); |
||||
$this->buildContentFiltering($grep, $this->contains); |
||||
$this->buildContentFiltering($grep, $this->notContains, true); |
||||
} |
||||
|
||||
if ($useSort) { |
||||
$this->buildSorting($command, $this->sort); |
||||
} |
||||
|
||||
$paths = $this->shell->testCommand('uniq') ? $command->add('| uniq')->execute() : array_unique($command->execute()); |
||||
$iterator = new Iterator\FilePathsIterator($paths, $dir); |
||||
|
||||
if ($this->exclude) { |
||||
$iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude); |
||||
} |
||||
|
||||
if (!$useGrep && ($this->contains || $this->notContains)) { |
||||
$iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains); |
||||
} |
||||
|
||||
if ($this->filters) { |
||||
$iterator = new Iterator\CustomFilterIterator($iterator, $this->filters); |
||||
} |
||||
|
||||
if (!$useSort && $this->sort) { |
||||
$iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort); |
||||
$iterator = $iteratorAggregate->getIterator(); |
||||
} |
||||
|
||||
return $iterator; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function canBeUsed() |
||||
{ |
||||
return $this->shell->testCommand('find'); |
||||
} |
||||
|
||||
/** |
||||
* @param Command $command |
||||
* @param string $dir |
||||
* |
||||
* @return Command |
||||
*/ |
||||
protected function buildFindCommand(Command $command, $dir) |
||||
{ |
||||
return $command |
||||
->ins('find') |
||||
->add('find ') |
||||
->arg($dir) |
||||
->add('-noleaf'); // the -noleaf option is required for filesystems that don't follow the '.' and '..' conventions |
||||
} |
||||
|
||||
/** |
||||
* @param Command $command |
||||
* @param string[] $names |
||||
* @param Boolean $not |
||||
*/ |
||||
private function buildNamesFiltering(Command $command, array $names, $not = false) |
||||
{ |
||||
if (0 === count($names)) { |
||||
return; |
||||
} |
||||
|
||||
$command->add($not ? '-not' : null)->cmd('('); |
||||
|
||||
foreach ($names as $i => $name) { |
||||
$expr = Expression::create($name); |
||||
|
||||
// Find does not support expandable globs ("*.{a,b}" syntax). |
||||
if ($expr->isGlob() && $expr->getGlob()->isExpandable()) { |
||||
$expr = Expression::create($expr->getGlob()->toRegex(false)); |
||||
} |
||||
|
||||
// Fixes 'not search' and 'full path matching' regex problems. |
||||
// - Jokers '.' are replaced by [^/]. |
||||
// - We add '[^/]*' before and after regex (if no ^|$ flags are present). |
||||
if ($expr->isRegex()) { |
||||
$regex = $expr->getRegex(); |
||||
$regex->prepend($regex->hasStartFlag() ? '/' : '/[^/]*') |
||||
->setStartFlag(false) |
||||
->setStartJoker(true) |
||||
->replaceJokers('[^/]'); |
||||
if (!$regex->hasEndFlag() || $regex->hasEndJoker()) { |
||||
$regex->setEndJoker(false)->append('[^/]*'); |
||||
} |
||||
} |
||||
|
||||
$command |
||||
->add($i > 0 ? '-or' : null) |
||||
->add($expr->isRegex() |
||||
? ($expr->isCaseSensitive() ? '-regex' : '-iregex') |
||||
: ($expr->isCaseSensitive() ? '-name' : '-iname') |
||||
) |
||||
->arg($expr->renderPattern()); |
||||
} |
||||
|
||||
$command->cmd(')'); |
||||
} |
||||
|
||||
/** |
||||
* @param Command $command |
||||
* @param string $dir |
||||
* @param string[] $paths |
||||
* @param Boolean $not |
||||
*/ |
||||
private function buildPathsFiltering(Command $command, $dir, array $paths, $not = false) |
||||
{ |
||||
if (0 === count($paths)) { |
||||
return; |
||||
} |
||||
|
||||
$command->add($not ? '-not' : null)->cmd('('); |
||||
|
||||
foreach ($paths as $i => $path) { |
||||
$expr = Expression::create($path); |
||||
|
||||
// Find does not support expandable globs ("*.{a,b}" syntax). |
||||
if ($expr->isGlob() && $expr->getGlob()->isExpandable()) { |
||||
$expr = Expression::create($expr->getGlob()->toRegex(false)); |
||||
} |
||||
|
||||
// Fixes 'not search' regex problems. |
||||
if ($expr->isRegex()) { |
||||
$regex = $expr->getRegex(); |
||||
$regex->prepend($regex->hasStartFlag() ? $dir.DIRECTORY_SEPARATOR : '.*')->setEndJoker(!$regex->hasEndFlag()); |
||||
} else { |
||||
$expr->prepend('*')->append('*'); |
||||
} |
||||
|
||||
$command |
||||
->add($i > 0 ? '-or' : null) |
||||
->add($expr->isRegex() |
||||
? ($expr->isCaseSensitive() ? '-regex' : '-iregex') |
||||
: ($expr->isCaseSensitive() ? '-path' : '-ipath') |
||||
) |
||||
->arg($expr->renderPattern()); |
||||
} |
||||
|
||||
$command->cmd(')'); |
||||
} |
||||
|
||||
/** |
||||
* @param Command $command |
||||
* @param NumberComparator[] $sizes |
||||
*/ |
||||
private function buildSizesFiltering(Command $command, array $sizes) |
||||
{ |
||||
foreach ($sizes as $i => $size) { |
||||
$command->add($i > 0 ? '-and' : null); |
||||
|
||||
switch ($size->getOperator()) { |
||||
case '<=': |
||||
$command->add('-size -' . ($size->getTarget() + 1) . 'c'); |
||||
break; |
||||
case '>=': |
||||
$command->add('-size +'. ($size->getTarget() - 1) . 'c'); |
||||
break; |
||||
case '>': |
||||
$command->add('-size +' . $size->getTarget() . 'c'); |
||||
break; |
||||
case '!=': |
||||
$command->add('-size -' . $size->getTarget() . 'c'); |
||||
$command->add('-size +' . $size->getTarget() . 'c'); |
||||
case '<': |
||||
default: |
||||
$command->add('-size -' . $size->getTarget() . 'c'); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @param Command $command |
||||
* @param DateComparator[] $dates |
||||
*/ |
||||
private function buildDatesFiltering(Command $command, array $dates) |
||||
{ |
||||
foreach ($dates as $i => $date) { |
||||
$command->add($i > 0 ? '-and' : null); |
||||
|
||||
$mins = (int) round((time()-$date->getTarget()) / 60); |
||||
|
||||
if (0 > $mins) { |
||||
// mtime is in the future |
||||
$command->add(' -mmin -0'); |
||||
// we will have no result so we don't need to continue |
||||
return; |
||||
} |
||||
|
||||
switch ($date->getOperator()) { |
||||
case '<=': |
||||
$command->add('-mmin +' . ($mins - 1)); |
||||
break; |
||||
case '>=': |
||||
$command->add('-mmin -' . ($mins + 1)); |
||||
break; |
||||
case '>': |
||||
$command->add('-mmin -' . $mins); |
||||
break; |
||||
case '!=': |
||||
$command->add('-mmin +' . $mins.' -or -mmin -' . $mins); |
||||
break; |
||||
case '<': |
||||
default: |
||||
$command->add('-mmin +' . $mins); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @param Command $command |
||||
* @param string $sort |
||||
* |
||||
* @throws \InvalidArgumentException |
||||
*/ |
||||
private function buildSorting(Command $command, $sort) |
||||
{ |
||||
$this->buildFormatSorting($command, $sort); |
||||
} |
||||
|
||||
/** |
||||
* @param Command $command |
||||
* @param string $sort |
||||
*/ |
||||
abstract protected function buildFormatSorting(Command $command, $sort); |
||||
|
||||
/** |
||||
* @param Command $command |
||||
* @param array $contains |
||||
* @param Boolean $not |
||||
*/ |
||||
abstract protected function buildContentFiltering(Command $command, array $contains, $not = false); |
||||
} |
||||
@ -1,137 +0,0 @@ |
||||
<?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\Adapter; |
||||
|
||||
/** |
||||
* @author Jean-François Simon <contact@jfsimon.fr> |
||||
*/ |
||||
interface AdapterInterface |
||||
{ |
||||
/** |
||||
* @param Boolean $followLinks |
||||
* |
||||
* @return AdapterInterface Current instance |
||||
*/ |
||||
public function setFollowLinks($followLinks); |
||||
|
||||
/** |
||||
* @param integer $mode |
||||
* |
||||
* @return AdapterInterface Current instance |
||||
*/ |
||||
public function setMode($mode); |
||||
|
||||
/** |
||||
* @param array $exclude |
||||
* |
||||
* @return AdapterInterface Current instance |
||||
*/ |
||||
public function setExclude(array $exclude); |
||||
|
||||
/** |
||||
* @param array $depths |
||||
* |
||||
* @return AdapterInterface Current instance |
||||
*/ |
||||
public function setDepths(array $depths); |
||||
|
||||
/** |
||||
* @param array $names |
||||
* |
||||
* @return AdapterInterface Current instance |
||||
*/ |
||||
public function setNames(array $names); |
||||
|
||||
/** |
||||
* @param array $notNames |
||||
* |
||||
* @return AdapterInterface Current instance |
||||
*/ |
||||
public function setNotNames(array $notNames); |
||||
|
||||
/** |
||||
* @param array $contains |
||||
* |
||||
* @return AdapterInterface Current instance |
||||
*/ |
||||
public function setContains(array $contains); |
||||
|
||||
/** |
||||
* @param array $notContains |
||||
* |
||||
* @return AdapterInterface Current instance |
||||
*/ |
||||
public function setNotContains(array $notContains); |
||||
|
||||
/** |
||||
* @param array $sizes |
||||
* |
||||
* @return AdapterInterface Current instance |
||||
*/ |
||||
public function setSizes(array $sizes); |
||||
|
||||
/** |
||||
* @param array $dates |
||||
* |
||||
* @return AdapterInterface Current instance |
||||
*/ |
||||
public function setDates(array $dates); |
||||
|
||||
/** |
||||
* @param array $filters |
||||
* |
||||
* @return AdapterInterface Current instance |
||||
*/ |
||||
public function setFilters(array $filters); |
||||
|
||||
/** |
||||
* @param \Closure|integer $sort |
||||
* |
||||
* @return AdapterInterface Current instance |
||||
*/ |
||||
public function setSort($sort); |
||||
|
||||
/** |
||||
* @param array $paths |
||||
* |
||||
* @return AdapterInterface Current instance |
||||
*/ |
||||
public function setPath(array $paths); |
||||
|
||||
/** |
||||
* @param array $notPaths |
||||
* |
||||
* @return AdapterInterface Current instance |
||||
*/ |
||||
public function setNotPath(array $notPaths); |
||||
|
||||
/** |
||||
* @param string $dir |
||||
* |
||||
* @return \Iterator Result iterator |
||||
*/ |
||||
public function searchInDirectory($dir); |
||||
|
||||
/** |
||||
* Tests adapter support for current platform. |
||||
* |
||||
* @return Boolean |
||||
*/ |
||||
public function isSupported(); |
||||
|
||||
/** |
||||
* Returns adapter name. |
||||
* |
||||
* @return string |
||||
*/ |
||||
public function getName(); |
||||
} |
||||
@ -1,101 +0,0 @@ |
||||
<?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\Adapter; |
||||
|
||||
use Symfony\Component\Finder\Shell\Shell; |
||||
use Symfony\Component\Finder\Shell\Command; |
||||
use Symfony\Component\Finder\Iterator\SortableIterator; |
||||
use Symfony\Component\Finder\Expression\Expression; |
||||
|
||||
/** |
||||
* Shell engine implementation using BSD find command. |
||||
* |
||||
* @author Jean-François Simon <contact@jfsimon.fr> |
||||
*/ |
||||
class BsdFindAdapter extends AbstractFindAdapter |
||||
{ |
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getName() |
||||
{ |
||||
return 'bsd_find'; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function canBeUsed() |
||||
{ |
||||
return in_array($this->shell->getType(), array(Shell::TYPE_BSD, Shell::TYPE_DARWIN)) && parent::canBeUsed(); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function buildFormatSorting(Command $command, $sort) |
||||
{ |
||||
switch ($sort) { |
||||
case SortableIterator::SORT_BY_NAME: |
||||
$command->ins('sort')->add('| sort'); |
||||
|
||||
return; |
||||
case SortableIterator::SORT_BY_TYPE: |
||||
$format = '%HT'; |
||||
break; |
||||
case SortableIterator::SORT_BY_ACCESSED_TIME: |
||||
$format = '%a'; |
||||
break; |
||||
case SortableIterator::SORT_BY_CHANGED_TIME: |
||||
$format = '%c'; |
||||
break; |
||||
case SortableIterator::SORT_BY_MODIFIED_TIME: |
||||
$format = '%m'; |
||||
break; |
||||
default: |
||||
throw new \InvalidArgumentException('Unknown sort options: '.$sort.'.'); |
||||
} |
||||
|
||||
$command |
||||
->add('-print0 | xargs -0 stat -f') |
||||
->arg($format.'%t%N') |
||||
->add('| sort | cut -f 2'); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function buildFindCommand(Command $command, $dir) |
||||
{ |
||||
parent::buildFindCommand($command, $dir)->addAtIndex('-E', 1); |
||||
|
||||
return $command; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function buildContentFiltering(Command $command, array $contains, $not = false) |
||||
{ |
||||
foreach ($contains as $contain) { |
||||
$expr = Expression::create($contain); |
||||
|
||||
// todo: avoid forking process for each $pattern by using multiple -e options |
||||
$command |
||||
->add('| grep -v \'^$\'') |
||||
->add('| xargs grep -I') |
||||
->add($expr->isCaseSensitive() ? null : '-i') |
||||
->add($not ? '-L' : '-l') |
||||
->add('-Ee')->arg($expr->renderPattern()); |
||||
} |
||||
} |
||||
} |
||||
@ -1,102 +0,0 @@ |
||||
<?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\Adapter; |
||||
|
||||
use Symfony\Component\Finder\Shell\Shell; |
||||
use Symfony\Component\Finder\Shell\Command; |
||||
use Symfony\Component\Finder\Iterator\SortableIterator; |
||||
use Symfony\Component\Finder\Expression\Expression; |
||||
|
||||
/** |
||||
* Shell engine implementation using GNU find command. |
||||
* |
||||
* @author Jean-François Simon <contact@jfsimon.fr> |
||||
*/ |
||||
class GnuFindAdapter extends AbstractFindAdapter |
||||
{ |
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getName() |
||||
{ |
||||
return 'gnu_find'; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function buildFormatSorting(Command $command, $sort) |
||||
{ |
||||
switch ($sort) { |
||||
case SortableIterator::SORT_BY_NAME: |
||||
$command->ins('sort')->add('| sort'); |
||||
|
||||
return; |
||||
case SortableIterator::SORT_BY_TYPE: |
||||
$format = '%y'; |
||||
break; |
||||
case SortableIterator::SORT_BY_ACCESSED_TIME: |
||||
$format = '%A@'; |
||||
break; |
||||
case SortableIterator::SORT_BY_CHANGED_TIME: |
||||
$format = '%C@'; |
||||
break; |
||||
case SortableIterator::SORT_BY_MODIFIED_TIME: |
||||
$format = '%T@'; |
||||
break; |
||||
default: |
||||
throw new \InvalidArgumentException('Unknown sort options: '.$sort.'.'); |
||||
} |
||||
|
||||
$command |
||||
->get('find') |
||||
->add('-printf') |
||||
->arg($format.' %h/%f\\n') |
||||
->add('| sort | cut') |
||||
->arg('-d ') |
||||
->arg('-f2-') |
||||
; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function canBeUsed() |
||||
{ |
||||
return $this->shell->getType() === Shell::TYPE_UNIX && parent::canBeUsed(); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function buildFindCommand(Command $command, $dir) |
||||
{ |
||||
return parent::buildFindCommand($command, $dir)->add('-regextype posix-extended'); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function buildContentFiltering(Command $command, array $contains, $not = false) |
||||
{ |
||||
foreach ($contains as $contain) { |
||||
$expr = Expression::create($contain); |
||||
|
||||
// todo: avoid forking process for each $pattern by using multiple -e options |
||||
$command |
||||
->add('| xargs -r grep -I') |
||||
->add($expr->isCaseSensitive() ? null : '-i') |
||||
->add($not ? '-L' : '-l') |
||||
->add('-Ee')->arg($expr->renderPattern()); |
||||
} |
||||
} |
||||
} |
||||
@ -1,98 +0,0 @@ |
||||
<?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\Adapter; |
||||
|
||||
use Symfony\Component\Finder\Iterator; |
||||
|
||||
/** |
||||
* PHP finder engine implementation. |
||||
* |
||||
* @author Jean-François Simon <contact@jfsimon.fr> |
||||
*/ |
||||
class PhpAdapter extends AbstractAdapter |
||||
{ |
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function searchInDirectory($dir) |
||||
{ |
||||
$flags = \RecursiveDirectoryIterator::SKIP_DOTS; |
||||
|
||||
if ($this->followLinks) { |
||||
$flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS; |
||||
} |
||||
|
||||
$iterator = new \RecursiveIteratorIterator( |
||||
new Iterator\RecursiveDirectoryIterator($dir, $flags), |
||||
\RecursiveIteratorIterator::SELF_FIRST |
||||
); |
||||
|
||||
if ($this->minDepth > 0 || $this->maxDepth < INF) { |
||||
$iterator = new Iterator\DepthRangeFilterIterator($iterator, $this->minDepth, $this->maxDepth); |
||||
} |
||||
|
||||
if ($this->mode) { |
||||
$iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode); |
||||
} |
||||
|
||||
if ($this->exclude) { |
||||
$iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude); |
||||
} |
||||
|
||||
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->sort) { |
||||
$iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort); |
||||
$iterator = $iteratorAggregate->getIterator(); |
||||
} |
||||
|
||||
if ($this->paths || $this->notPaths) { |
||||
$iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths); |
||||
} |
||||
|
||||
return $iterator; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getName() |
||||
{ |
||||
return 'php'; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function canBeUsed() |
||||
{ |
||||
return true; |
||||
} |
||||
} |
||||
@ -1,46 +0,0 @@ |
||||
<?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; |
||||
|
||||
use Symfony\Component\Finder\Adapter\AdapterInterface; |
||||
|
||||
/** |
||||
* Base exception for all adapter failures. |
||||
* |
||||
* @author Jean-François Simon <contact@jfsimon.fr> |
||||
*/ |
||||
class AdapterFailureException extends \RuntimeException implements ExceptionInterface |
||||
{ |
||||
/** |
||||
* @var \Symfony\Component\Finder\Adapter\AdapterInterface |
||||
*/ |
||||
private $adapter; |
||||
|
||||
/** |
||||
* @param AdapterInterface $adapter |
||||
* @param string|null $message |
||||
* @param \Exception|null $previous |
||||
*/ |
||||
public function __construct(AdapterInterface $adapter, $message = null, \Exception $previous = null) |
||||
{ |
||||
$this->adapter = $adapter; |
||||
parent::__construct($message ?: 'Search failed with "'.$adapter->getName().'" adapter.', $previous); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getAdapter() |
||||
{ |
||||
return $this->adapter; |
||||
} |
||||
} |
||||
@ -1,14 +0,0 @@ |
||||
<?php |
||||
|
||||
namespace Symfony\Component\Finder\Exception; |
||||
|
||||
/** |
||||
* @author Jean-François Simon <contact@jfsimon.fr> |
||||
*/ |
||||
interface ExceptionInterface |
||||
{ |
||||
/** |
||||
* @return \Symfony\Component\Finder\Adapter\AdapterInterface |
||||
*/ |
||||
public function getAdapter(); |
||||
} |
||||
@ -1,19 +0,0 @@ |
||||
<?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> |
||||
*/ |
||||
class OperationNotPermitedException extends AdapterFailureException |
||||
{ |
||||
} |
||||
@ -1,45 +0,0 @@ |
||||
<?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; |
||||
|
||||
use Symfony\Component\Finder\Adapter\AdapterInterface; |
||||
use Symfony\Component\Finder\Shell\Command; |
||||
|
||||
/** |
||||
* @author Jean-François Simon <contact@jfsimon.fr> |
||||
*/ |
||||
class ShellCommandFailureException extends AdapterFailureException |
||||
{ |
||||
/** |
||||
* @var Command |
||||
*/ |
||||
private $command; |
||||
|
||||
/** |
||||
* @param AdapterInterface $adapter |
||||
* @param Command $command |
||||
* @param \Exception|null $previous |
||||
*/ |
||||
public function __construct(AdapterInterface $adapter, Command $command, \Exception $previous = null) |
||||
{ |
||||
$this->command = $command; |
||||
parent::__construct($adapter, 'Shell command failed: "'.$command->join().'".', $previous); |
||||
} |
||||
|
||||
/** |
||||
* @return Command |
||||
*/ |
||||
public function getCommand() |
||||
{ |
||||
return $this->command; |
||||
} |
||||
} |
||||
@ -1,146 +0,0 @@ |
||||
<?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\Expression; |
||||
|
||||
/** |
||||
* @author Jean-François Simon <contact@jfsimon.fr> |
||||
*/ |
||||
class Expression implements ValueInterface |
||||
{ |
||||
const TYPE_REGEX = 1; |
||||
const TYPE_GLOB = 2; |
||||
|
||||
/** |
||||
* @var ValueInterface |
||||
*/ |
||||
private $value; |
||||
|
||||
/** |
||||
* @param string $expr |
||||
* |
||||
* @return Expression |
||||
*/ |
||||
public static function create($expr) |
||||
{ |
||||
return new self($expr); |
||||
} |
||||
|
||||
/** |
||||
* @param string $expr |
||||
*/ |
||||
public function __construct($expr) |
||||
{ |
||||
try { |
||||
$this->value = Regex::create($expr); |
||||
} catch (\InvalidArgumentException $e) { |
||||
$this->value = new Glob($expr); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @return string |
||||
*/ |
||||
public function __toString() |
||||
{ |
||||
return $this->render(); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function render() |
||||
{ |
||||
return $this->value->render(); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function renderPattern() |
||||
{ |
||||
return $this->value->renderPattern(); |
||||
} |
||||
|
||||
/** |
||||
* @return bool |
||||
*/ |
||||
public function isCaseSensitive() |
||||
{ |
||||
return $this->value->isCaseSensitive(); |
||||
} |
||||
|
||||
/** |
||||
* @return int |
||||
*/ |
||||
public function getType() |
||||
{ |
||||
return $this->value->getType(); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function prepend($expr) |
||||
{ |
||||
$this->value->prepend($expr); |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function append($expr) |
||||
{ |
||||
$this->value->append($expr); |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* @return bool |
||||
*/ |
||||
public function isRegex() |
||||
{ |
||||
return self::TYPE_REGEX === $this->value->getType(); |
||||
} |
||||
|
||||
/** |
||||
* @return bool |
||||
*/ |
||||
public function isGlob() |
||||
{ |
||||
return self::TYPE_GLOB === $this->value->getType(); |
||||
} |
||||
|
||||
/** |
||||
* @throws \LogicException |
||||
* |
||||
* @return Glob |
||||
*/ |
||||
public function getGlob() |
||||
{ |
||||
if (self::TYPE_GLOB !== $this->value->getType()) { |
||||
throw new \LogicException('Regex cant be transformed to glob.'); |
||||
} |
||||
|
||||
return $this->value; |
||||
} |
||||
|
||||
/** |
||||
* @return Regex |
||||
*/ |
||||
public function getRegex() |
||||
{ |
||||
return self::TYPE_REGEX === $this->value->getType() ? $this->value : $this->value->toRegex(); |
||||
} |
||||
} |
||||
@ -1,157 +0,0 @@ |
||||
<?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\Expression; |
||||
|
||||
/** |
||||
* @author Jean-François Simon <contact@jfsimon.fr> |
||||
*/ |
||||
class Glob implements ValueInterface |
||||
{ |
||||
/** |
||||
* @var string |
||||
*/ |
||||
private $pattern; |
||||
|
||||
/** |
||||
* @param string $pattern |
||||
*/ |
||||
public function __construct($pattern) |
||||
{ |
||||
$this->pattern = $pattern; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function render() |
||||
{ |
||||
return $this->pattern; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function renderPattern() |
||||
{ |
||||
return $this->pattern; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getType() |
||||
{ |
||||
return Expression::TYPE_GLOB; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function isCaseSensitive() |
||||
{ |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function prepend($expr) |
||||
{ |
||||
$this->pattern = $expr.$this->pattern; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function append($expr) |
||||
{ |
||||
$this->pattern .= $expr; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* Tests if glob is expandable ("*.{a,b}" syntax). |
||||
* |
||||
* @return bool |
||||
*/ |
||||
public function isExpandable() |
||||
{ |
||||
return false !== strpos($this->pattern, '{') |
||||
&& false !== strpos($this->pattern, '}'); |
||||
} |
||||
|
||||
/** |
||||
* @param bool $strictLeadingDot |
||||
* @param bool $strictWildcardSlash |
||||
* |
||||
* @return Regex |
||||
*/ |
||||
public function toRegex($strictLeadingDot = true, $strictWildcardSlash = true) |
||||
{ |
||||
$firstByte = true; |
||||
$escaping = false; |
||||
$inCurlies = 0; |
||||
$regex = ''; |
||||
$sizeGlob = strlen($this->pattern); |
||||
for ($i = 0; $i < $sizeGlob; $i++) { |
||||
$car = $this->pattern[$i]; |
||||
if ($firstByte) { |
||||
if ($strictLeadingDot && '.' !== $car) { |
||||
$regex .= '(?=[^\.])'; |
||||
} |
||||
|
||||
$firstByte = false; |
||||
} |
||||
|
||||
if ('/' === $car) { |
||||
$firstByte = true; |
||||
} |
||||
|
||||
if ('.' === $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 new Regex('^'.$regex.'$'); |
||||
} |
||||
} |
||||
@ -1,317 +0,0 @@ |
||||
<?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\Expression; |
||||
|
||||
/** |
||||
* @author Jean-François Simon <contact@jfsimon.fr> |
||||
*/ |
||||
class Regex implements ValueInterface |
||||
{ |
||||
const START_FLAG = '^'; |
||||
const END_FLAG = '$'; |
||||
const BOUNDARY = '~'; |
||||
const JOKER = '.*'; |
||||
const ESCAPING = '\\'; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
private $pattern; |
||||
|
||||
/** |
||||
* @var array |
||||
*/ |
||||
private $options; |
||||
|
||||
/** |
||||
* @var bool |
||||
*/ |
||||
private $startFlag; |
||||
|
||||
/** |
||||
* @var bool |
||||
*/ |
||||
private $endFlag; |
||||
|
||||
/** |
||||
* @var bool |
||||
*/ |
||||
private $startJoker; |
||||
|
||||
/** |
||||
* @var bool |
||||
*/ |
||||
private $endJoker; |
||||
|
||||
/** |
||||
* @param string $expr |
||||
* |
||||
* @return Regex |
||||
* |
||||
* @throws \InvalidArgumentException |
||||
*/ |
||||
public static function create($expr) |
||||
{ |
||||
if (preg_match('/^(.{3,}?)([imsxuADU]*)$/', $expr, $m)) { |
||||
$start = substr($m[1], 0, 1); |
||||
$end = substr($m[1], -1); |
||||
|
||||
if (($start === $end && !preg_match('/[*?[:alnum:] \\\\]/', $start)) || ($start === '{' && $end === '}')) { |
||||
return new self(substr($m[1], 1, -1), $m[2], $end); |
||||
} |
||||
} |
||||
|
||||
throw new \InvalidArgumentException('Given expression is not a regex.'); |
||||
} |
||||
|
||||
/** |
||||
* @param string $pattern |
||||
* @param string $options |
||||
* @param string $delimiter |
||||
*/ |
||||
public function __construct($pattern, $options = '', $delimiter = null) |
||||
{ |
||||
if (null !== $delimiter) { |
||||
// removes delimiter escaping |
||||
$pattern = str_replace('\\'.$delimiter, $delimiter, $pattern); |
||||
} |
||||
|
||||
$this->parsePattern($pattern); |
||||
$this->options = $options; |
||||
} |
||||
|
||||
/** |
||||
* @return string |
||||
*/ |
||||
public function __toString() |
||||
{ |
||||
return $this->render(); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function render() |
||||
{ |
||||
return self::BOUNDARY |
||||
.$this->renderPattern() |
||||
.self::BOUNDARY |
||||
.$this->options; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function renderPattern() |
||||
{ |
||||
return ($this->startFlag ? self::START_FLAG : '') |
||||
.($this->startJoker ? self::JOKER : '') |
||||
.str_replace(self::BOUNDARY, '\\'.self::BOUNDARY, $this->pattern) |
||||
.($this->endJoker ? self::JOKER : '') |
||||
.($this->endFlag ? self::END_FLAG : ''); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function isCaseSensitive() |
||||
{ |
||||
return !$this->hasOption('i'); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getType() |
||||
{ |
||||
return Expression::TYPE_REGEX; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function prepend($expr) |
||||
{ |
||||
$this->pattern = $expr.$this->pattern; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function append($expr) |
||||
{ |
||||
$this->pattern .= $expr; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* @param string $option |
||||
* |
||||
* @return bool |
||||
*/ |
||||
public function hasOption($option) |
||||
{ |
||||
return false !== strpos($this->options, $option); |
||||
} |
||||
|
||||
/** |
||||
* @param string $option |
||||
* |
||||
* @return Regex |
||||
*/ |
||||
public function addOption($option) |
||||
{ |
||||
if (!$this->hasOption($option)) { |
||||
$this->options.= $option; |
||||
} |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* @param string $option |
||||
* |
||||
* @return Regex |
||||
*/ |
||||
public function removeOption($option) |
||||
{ |
||||
$this->options = str_replace($option, '', $this->options); |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* @param bool $startFlag |
||||
* |
||||
* @return Regex |
||||
*/ |
||||
public function setStartFlag($startFlag) |
||||
{ |
||||
$this->startFlag = $startFlag; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* @return bool |
||||
*/ |
||||
public function hasStartFlag() |
||||
{ |
||||
return $this->startFlag; |
||||
} |
||||
|
||||
/** |
||||
* @param bool $endFlag |
||||
* |
||||
* @return Regex |
||||
*/ |
||||
public function setEndFlag($endFlag) |
||||
{ |
||||
$this->endFlag = (bool) $endFlag; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* @return bool |
||||
*/ |
||||
public function hasEndFlag() |
||||
{ |
||||
return $this->endFlag; |
||||
} |
||||
|
||||
/** |
||||
* @param bool $startJoker |
||||
* |
||||
* @return Regex |
||||
*/ |
||||
public function setStartJoker($startJoker) |
||||
{ |
||||
$this->startJoker = $startJoker; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* @return bool |
||||
*/ |
||||
public function hasStartJoker() |
||||
{ |
||||
return $this->startJoker; |
||||
} |
||||
|
||||
/** |
||||
* @param bool $endJoker |
||||
* |
||||
* @return Regex |
||||
*/ |
||||
public function setEndJoker($endJoker) |
||||
{ |
||||
$this->endJoker = (bool) $endJoker; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* @return bool |
||||
*/ |
||||
public function hasEndJoker() |
||||
{ |
||||
return $this->endJoker; |
||||
} |
||||
|
||||
/** |
||||
* @param array $replacement |
||||
* |
||||
* @return Regex |
||||
*/ |
||||
public function replaceJokers($replacement) |
||||
{ |
||||
$replace = function ($subject) use ($replacement) { |
||||
$subject = $subject[0]; |
||||
$replace = 0 === substr_count($subject, '\\') % 2; |
||||
|
||||
return $replace ? str_replace('.', $replacement, $subject) : $subject; |
||||
}; |
||||
|
||||
$this->pattern = preg_replace_callback('~[\\\\]*\\.~', $replace, $this->pattern); |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* @param string $pattern |
||||
*/ |
||||
private function parsePattern($pattern) |
||||
{ |
||||
if ($this->startFlag = self::START_FLAG === substr($pattern, 0, 1)) { |
||||
$pattern = substr($pattern, 1); |
||||
} |
||||
|
||||
if ($this->startJoker = self::JOKER === substr($pattern, 0, 2)) { |
||||
$pattern = substr($pattern, 2); |
||||
} |
||||
|
||||
if ($this->endFlag = (self::END_FLAG === substr($pattern, -1) && self::ESCAPING !== substr($pattern, -2, -1))) { |
||||
$pattern = substr($pattern, 0, -1); |
||||
} |
||||
|
||||
if ($this->endJoker = (self::JOKER === substr($pattern, -2) && self::ESCAPING !== substr($pattern, -3, -2))) { |
||||
$pattern = substr($pattern, 0, -2); |
||||
} |
||||
|
||||
$this->pattern = $pattern; |
||||
} |
||||
} |
||||
@ -1,60 +0,0 @@ |
||||
<?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\Expression; |
||||
|
||||
/** |
||||
* @author Jean-François Simon <contact@jfsimon.fr> |
||||
*/ |
||||
interface ValueInterface |
||||
{ |
||||
/** |
||||
* Renders string representation of expression. |
||||
* |
||||
* @return string |
||||
*/ |
||||
public function render(); |
||||
|
||||
/** |
||||
* Renders string representation of pattern. |
||||
* |
||||
* @return string |
||||
*/ |
||||
public function renderPattern(); |
||||
|
||||
/** |
||||
* Returns value case sensitivity. |
||||
* |
||||
* @return bool |
||||
*/ |
||||
public function isCaseSensitive(); |
||||
|
||||
/** |
||||
* Returns expression type. |
||||
* |
||||
* @return int |
||||
*/ |
||||
public function getType(); |
||||
|
||||
/** |
||||
* @param string $expr |
||||
* |
||||
* @return ValueInterface |
||||
*/ |
||||
public function prepend($expr); |
||||
|
||||
/** |
||||
* @param string $expr |
||||
* |
||||
* @return ValueInterface |
||||
*/ |
||||
public function append($expr); |
||||
} |
||||
@ -1,131 +0,0 @@ |
||||
<?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\SplFileInfo; |
||||
|
||||
/** |
||||
* Iterate over shell command result. |
||||
* |
||||
* @author Jean-François Simon <contact@jfsimon.fr> |
||||
*/ |
||||
class FilePathsIterator extends \ArrayIterator |
||||
{ |
||||
/** |
||||
* @var string |
||||
*/ |
||||
private $baseDir; |
||||
|
||||
/** |
||||
* @var int |
||||
*/ |
||||
private $baseDirLength; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
private $subPath; |
||||
|
||||
/** |
||||
* @var string |
||||
*/ |
||||
private $subPathname; |
||||
|
||||
/** |
||||
* @var SplFileInfo |
||||
*/ |
||||
private $current; |
||||
|
||||
/** |
||||
* @param array $paths List of paths returned by shell command |
||||
* @param string $baseDir Base dir for relative path building |
||||
*/ |
||||
public function __construct(array $paths, $baseDir) |
||||
{ |
||||
$this->baseDir = $baseDir; |
||||
$this->baseDirLength = strlen($baseDir); |
||||
|
||||
parent::__construct($paths); |
||||
} |
||||
|
||||
/** |
||||
* @param string $name |
||||
* @param array $arguments |
||||
* |
||||
* @return mixed |
||||
*/ |
||||
public function __call($name, array $arguments) |
||||
{ |
||||
return call_user_func_array(array($this->current(), $name), $arguments); |
||||
} |
||||
|
||||
/** |
||||
* Return an instance of SplFileInfo with support for relative paths. |
||||
* |
||||
* @return SplFileInfo File information |
||||
*/ |
||||
public function current() |
||||
{ |
||||
return $this->current; |
||||
} |
||||
|
||||
/** |
||||
* @return string |
||||
*/ |
||||
public function key() |
||||
{ |
||||
return $this->current->getPathname(); |
||||
} |
||||
|
||||
public function next() |
||||
{ |
||||
parent::next(); |
||||
$this->buildProperties(); |
||||
} |
||||
|
||||
public function rewind() |
||||
{ |
||||
parent::rewind(); |
||||
$this->buildProperties(); |
||||
} |
||||
|
||||
/** |
||||
* @return string |
||||
*/ |
||||
public function getSubPath() |
||||
{ |
||||
return $this->subPath; |
||||
} |
||||
|
||||
/** |
||||
* @return string |
||||
*/ |
||||
public function getSubPathname() |
||||
{ |
||||
return $this->subPathname; |
||||
} |
||||
|
||||
private function buildProperties() |
||||
{ |
||||
$absolutePath = parent::current(); |
||||
|
||||
if ($this->baseDir === substr($absolutePath, 0, $this->baseDirLength)) { |
||||
$this->subPathname = ltrim(substr($absolutePath, $this->baseDirLength), '/\\'); |
||||
$dir = dirname($this->subPathname); |
||||
$this->subPath = '.' === $dir ? '' : $dir; |
||||
} else { |
||||
$this->subPath = $this->subPathname = ''; |
||||
} |
||||
|
||||
$this->current = new SplFileInfo(parent::current(), $this->subPath, $this->subPathname); |
||||
} |
||||
} |
||||
@ -1,75 +0,0 @@ |
||||
<?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 Boolean true if the value should be kept, false otherwise |
||||
*/ |
||||
public function accept() |
||||
{ |
||||
$filename = $this->current()->getRelativePathname(); |
||||
|
||||
if (defined('PHP_WINDOWS_VERSION_MAJOR')) { |
||||
$filename = strtr($filename, '\\', '/'); |
||||
} |
||||
|
||||
// should at least not match one rule to exclude |
||||
foreach ($this->noMatchRegexps as $regex) { |
||||
if (preg_match($regex, $filename)) { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
// should at least match one rule |
||||
$match = true; |
||||
if ($this->matchRegexps) { |
||||
$match = false; |
||||
foreach ($this->matchRegexps as $regex) { |
||||
if (preg_match($regex, $filename)) { |
||||
return true; |
||||
} |
||||
} |
||||
} |
||||
|
||||
return $match; |
||||
} |
||||
|
||||
/** |
||||
* 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, '/').'/'; |
||||
} |
||||
} |
||||
@ -1,264 +0,0 @@ |
||||
<?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\Shell; |
||||
|
||||
/** |
||||
* @author Jean-François Simon <contact@jfsimon.fr> |
||||
*/ |
||||
class Command |
||||
{ |
||||
/** |
||||
* @var Command|null |
||||
*/ |
||||
private $parent; |
||||
|
||||
/** |
||||
* @var array |
||||
*/ |
||||
private $bits; |
||||
|
||||
/** |
||||
* @var array |
||||
*/ |
||||
private $labels; |
||||
|
||||
/** |
||||
* Constructor. |
||||
* |
||||
* @param Command $parent Parent command |
||||
*/ |
||||
public function __construct(Command $parent = null) |
||||
{ |
||||
$this->parent = $parent; |
||||
$this->bits = array(); |
||||
$this->labels = array(); |
||||
} |
||||
|
||||
/** |
||||
* Returns command as string. |
||||
* |
||||
* @return string |
||||
*/ |
||||
public function __toString() |
||||
{ |
||||
return $this->join(); |
||||
} |
||||
|
||||
/** |
||||
* Creates a new Command instance. |
||||
* |
||||
* @param Command $parent Parent command |
||||
* |
||||
* @return Command New Command instance |
||||
*/ |
||||
public static function create(Command $parent = null) |
||||
{ |
||||
return new self($parent); |
||||
} |
||||
|
||||
/** |
||||
* Escapes special chars from input. |
||||
* |
||||
* @param string $input A string to escape |
||||
* |
||||
* @return string The escaped string |
||||
*/ |
||||
public static function escape($input) |
||||
{ |
||||
return escapeshellcmd($input); |
||||
} |
||||
|
||||
/** |
||||
* Quotes input. |
||||
* |
||||
* @param string $input An argument string |
||||
* |
||||
* @return string The quoted string |
||||
*/ |
||||
public static function quote($input) |
||||
{ |
||||
return escapeshellarg($input); |
||||
} |
||||
|
||||
/** |
||||
* Appends a string or a Command instance. |
||||
* |
||||
* @param string|Command $bit |
||||
* |
||||
* @return Command The current Command instance |
||||
*/ |
||||
public function add($bit) |
||||
{ |
||||
$this->bits[] = $bit; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* Prepends a string or a command instance. |
||||
* |
||||
* @param string|Command $bit |
||||
* |
||||
* @return Command The current Command instance |
||||
*/ |
||||
public function top($bit) |
||||
{ |
||||
array_unshift($this->bits, $bit); |
||||
|
||||
foreach ($this->labels as $label => $index) { |
||||
$this->labels[$label] += 1; |
||||
} |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* Appends an argument, will be quoted. |
||||
* |
||||
* @param string $arg |
||||
* |
||||
* @return Command The current Command instance |
||||
*/ |
||||
public function arg($arg) |
||||
{ |
||||
$this->bits[] = self::quote($arg); |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* Appends escaped special command chars. |
||||
* |
||||
* @param string $esc |
||||
* |
||||
* @return Command The current Command instance |
||||
*/ |
||||
public function cmd($esc) |
||||
{ |
||||
$this->bits[] = self::escape($esc); |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* Inserts a labeled command to feed later. |
||||
* |
||||
* @param string $label The unique label |
||||
* |
||||
* @return Command The current Command instance |
||||
* |
||||
* @throws \RuntimeException If label already exists |
||||
*/ |
||||
public function ins($label) |
||||
{ |
||||
if (isset($this->labels[$label])) { |
||||
throw new \RuntimeException('Label "'.$label.'" already exists.'); |
||||
} |
||||
|
||||
$this->bits[] = self::create($this); |
||||
$this->labels[$label] = count($this->bits)-1; |
||||
|
||||
return $this->bits[$this->labels[$label]]; |
||||
} |
||||
|
||||
/** |
||||
* Retrieves a previously labeled command. |
||||
* |
||||
* @param string $label |
||||
* |
||||
* @return Command The labeled command |
||||
* |
||||
* @throws \RuntimeException |
||||
*/ |
||||
public function get($label) |
||||
{ |
||||
if (!isset($this->labels[$label])) { |
||||
throw new \RuntimeException('Label "'.$label.'" does not exists.'); |
||||
} |
||||
|
||||
return $this->bits[$this->labels[$label]]; |
||||
} |
||||
|
||||
/** |
||||
* Returns parent command (if any). |
||||
* |
||||
* @return Command Parent command |
||||
* |
||||
* @throws \RuntimeException If command has no parent |
||||
*/ |
||||
public function end() |
||||
{ |
||||
if (null === $this->parent) { |
||||
throw new \RuntimeException('Calling end on root command doesn\'t make sense.'); |
||||
} |
||||
|
||||
return $this->parent; |
||||
} |
||||
|
||||
/** |
||||
* Counts bits stored in command. |
||||
* |
||||
* @return int The bits count |
||||
*/ |
||||
public function length() |
||||
{ |
||||
return count($this->bits); |
||||
} |
||||
|
||||
/** |
||||
* Executes current command. |
||||
* |
||||
* @return array The command result |
||||
* |
||||
* @throws \RuntimeException |
||||
*/ |
||||
public function execute() |
||||
{ |
||||
exec($this->join(), $output, $code); |
||||
|
||||
if (0 !== $code) { |
||||
throw new \RuntimeException('Execution failed with return code: '.$code.'.'); |
||||
} |
||||
|
||||
return $output ?: array(); |
||||
} |
||||
|
||||
/** |
||||
* Joins bits. |
||||
* |
||||
* @return string |
||||
*/ |
||||
public function join() |
||||
{ |
||||
return implode(' ', array_filter( |
||||
array_map(function($bit) { |
||||
return $bit instanceof Command ? $bit->join() : ($bit ?: null); |
||||
}, $this->bits), |
||||
function($bit) { return null !== $bit; } |
||||
)); |
||||
} |
||||
|
||||
/** |
||||
* Insert a string or a Command instance before the bit at given position $index (index starts from 0). |
||||
* |
||||
* @param string|Command $bit |
||||
* @param integer $index |
||||
* |
||||
* @return Command The current Command instance |
||||
*/ |
||||
public function addAtIndex($bit, $index) |
||||
{ |
||||
array_splice($this->bits, $index, 0, $bit); |
||||
|
||||
return $this; |
||||
} |
||||
} |
||||
@ -1,95 +0,0 @@ |
||||
<?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\Shell; |
||||
|
||||
/** |
||||
* @author Jean-François Simon <contact@jfsimon.fr> |
||||
*/ |
||||
class Shell |
||||
{ |
||||
const TYPE_UNIX = 1; |
||||
const TYPE_DARWIN = 2; |
||||
const TYPE_CYGWIN = 3; |
||||
const TYPE_WINDOWS = 4; |
||||
const TYPE_BSD = 5; |
||||
|
||||
/** |
||||
* @var string|null |
||||
*/ |
||||
private $type; |
||||
|
||||
/** |
||||
* Returns guessed OS type. |
||||
* |
||||
* @return int |
||||
*/ |
||||
public function getType() |
||||
{ |
||||
if (null === $this->type) { |
||||
$this->type = $this->guessType(); |
||||
} |
||||
|
||||
return $this->type; |
||||
} |
||||
|
||||
/** |
||||
* Tests if a command is available. |
||||
* |
||||
* @param string $command |
||||
* |
||||
* @return bool |
||||
*/ |
||||
public function testCommand($command) |
||||
{ |
||||
if (self::TYPE_WINDOWS === $this->type) { |
||||
// todo: find a way to test if windows command exists |
||||
return false; |
||||
} |
||||
|
||||
if (!function_exists('exec')) { |
||||
return false; |
||||
} |
||||
|
||||
// todo: find a better way (command could not be available) |
||||
exec('command -v '.$command, $output, $code); |
||||
|
||||
return 0 === $code && count($output) > 0; |
||||
} |
||||
|
||||
/** |
||||
* Guesses OS type. |
||||
* |
||||
* @return int |
||||
*/ |
||||
private function guessType() |
||||
{ |
||||
$os = strtolower(PHP_OS); |
||||
|
||||
if (false !== strpos($os, 'cygwin')) { |
||||
return self::TYPE_CYGWIN; |
||||
} |
||||
|
||||
if (false !== strpos($os, 'darwin')) { |
||||
return self::TYPE_DARWIN; |
||||
} |
||||
|
||||
if (false !== strpos($os, 'bsd')) { |
||||
return self::TYPE_BSD; |
||||
} |
||||
|
||||
if (0 === strpos($os, 'win')) { |
||||
return self::TYPE_WINDOWS; |
||||
} |
||||
|
||||
return self::TYPE_UNIX; |
||||
} |
||||
} |
||||
@ -1,68 +0,0 @@ |
||||
<?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\Expression\Expression; |
||||
|
||||
class ExpressionTest extends \PHPUnit_Framework_TestCase |
||||
{ |
||||
/** |
||||
* @dataProvider getTypeGuesserData |
||||
*/ |
||||
public function testTypeGuesser($expr, $type) |
||||
{ |
||||
$this->assertEquals($type, Expression::create($expr)->getType()); |
||||
} |
||||
|
||||
/** |
||||
* @dataProvider getCaseSensitiveData |
||||
*/ |
||||
public function testCaseSensitive($expr, $isCaseSensitive) |
||||
{ |
||||
$this->assertEquals($isCaseSensitive, Expression::create($expr)->isCaseSensitive()); |
||||
} |
||||
|
||||
/** |
||||
* @dataProvider getRegexRenderingData |
||||
*/ |
||||
public function testRegexRendering($expr, $body) |
||||
{ |
||||
$this->assertEquals($body, Expression::create($expr)->renderPattern()); |
||||
} |
||||
|
||||
public function getTypeGuesserData() |
||||
{ |
||||
return array( |
||||
array('{foo}', Expression::TYPE_REGEX), |
||||
array('/foo/', Expression::TYPE_REGEX), |
||||
array('foo', Expression::TYPE_GLOB), |
||||
array('foo*', Expression::TYPE_GLOB), |
||||
); |
||||
} |
||||
|
||||
public function getCaseSensitiveData() |
||||
{ |
||||
return array( |
||||
array('{foo}m', true), |
||||
array('/foo/i', false), |
||||
array('foo*', true), |
||||
); |
||||
} |
||||
|
||||
public function getRegexRenderingData() |
||||
{ |
||||
return array( |
||||
array('{foo}m', 'foo'), |
||||
array('/foo/i', 'foo'), |
||||
); |
||||
} |
||||
} |
||||
@ -1,143 +0,0 @@ |
||||
<?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\Expression\Expression; |
||||
|
||||
class RegexTest extends \PHPUnit_Framework_TestCase |
||||
{ |
||||
/** |
||||
* @dataProvider getHasFlagsData |
||||
*/ |
||||
public function testHasFlags($regex, $start, $end) |
||||
{ |
||||
$expr = new Expression($regex); |
||||
|
||||
$this->assertEquals($start, $expr->getRegex()->hasStartFlag()); |
||||
$this->assertEquals($end, $expr->getRegex()->hasEndFlag()); |
||||
} |
||||
|
||||
/** |
||||
* @dataProvider getHasJokersData |
||||
*/ |
||||
public function testHasJokers($regex, $start, $end) |
||||
{ |
||||
$expr = new Expression($regex); |
||||
|
||||
$this->assertEquals($start, $expr->getRegex()->hasStartJoker()); |
||||
$this->assertEquals($end, $expr->getRegex()->hasEndJoker()); |
||||
} |
||||
|
||||
/** |
||||
* @dataProvider getSetFlagsData |
||||
*/ |
||||
public function testSetFlags($regex, $start, $end, $expected) |
||||
{ |
||||
$expr = new Expression($regex); |
||||
$expr->getRegex()->setStartFlag($start)->setEndFlag($end); |
||||
|
||||
$this->assertEquals($expected, $expr->render()); |
||||
} |
||||
|
||||
/** |
||||
* @dataProvider getSetJokersData |
||||
*/ |
||||
public function testSetJokers($regex, $start, $end, $expected) |
||||
{ |
||||
$expr = new Expression($regex); |
||||
$expr->getRegex()->setStartJoker($start)->setEndJoker($end); |
||||
|
||||
$this->assertEquals($expected, $expr->render()); |
||||
} |
||||
|
||||
public function testOptions() |
||||
{ |
||||
$expr = new Expression('~abc~is'); |
||||
$expr->getRegex()->removeOption('i')->addOption('m'); |
||||
|
||||
$this->assertEquals('~abc~sm', $expr->render()); |
||||
} |
||||
|
||||
public function testMixFlagsAndJokers() |
||||
{ |
||||
$expr = new Expression('~^.*abc.*$~is'); |
||||
|
||||
$expr->getRegex()->setStartFlag(false)->setEndFlag(false)->setStartJoker(false)->setEndJoker(false); |
||||
$this->assertEquals('~abc~is', $expr->render()); |
||||
|
||||
$expr->getRegex()->setStartFlag(true)->setEndFlag(true)->setStartJoker(true)->setEndJoker(true); |
||||
$this->assertEquals('~^.*abc.*$~is', $expr->render()); |
||||
} |
||||
|
||||
/** |
||||
* @dataProvider getReplaceJokersTestData |
||||
*/ |
||||
public function testReplaceJokers($regex, $expected) |
||||
{ |
||||
$expr = new Expression($regex); |
||||
$expr = $expr->getRegex()->replaceJokers('@'); |
||||
|
||||
$this->assertEquals($expected, $expr->renderPattern()); |
||||
} |
||||
|
||||
public function getHasFlagsData() |
||||
{ |
||||
return array( |
||||
array('~^abc~', true, false), |
||||
array('~abc$~', false, true), |
||||
array('~abc~', false, false), |
||||
array('~^abc$~', true, true), |
||||
array('~^abc\\$~', true, false), |
||||
); |
||||
} |
||||
|
||||
public function getHasJokersData() |
||||
{ |
||||
return array( |
||||
array('~.*abc~', true, false), |
||||
array('~abc.*~', false, true), |
||||
array('~abc~', false, false), |
||||
array('~.*abc.*~', true, true), |
||||
array('~.*abc\\.*~', true, false), |
||||
); |
||||
} |
||||
|
||||
public function getSetFlagsData() |
||||
{ |
||||
return array( |
||||
array('~abc~', true, false, '~^abc~'), |
||||
array('~abc~', false, true, '~abc$~'), |
||||
array('~abc~', false, false, '~abc~'), |
||||
array('~abc~', true, true, '~^abc$~'), |
||||
); |
||||
} |
||||
|
||||
public function getSetJokersData() |
||||
{ |
||||
return array( |
||||
array('~abc~', true, false, '~.*abc~'), |
||||
array('~abc~', false, true, '~abc.*~'), |
||||
array('~abc~', false, false, '~abc~'), |
||||
array('~abc~', true, true, '~.*abc.*~'), |
||||
); |
||||
} |
||||
|
||||
public function getReplaceJokersTestData() |
||||
{ |
||||
return array( |
||||
array('~.abc~', '@abc'), |
||||
array('~\\.abc~', '\\.abc'), |
||||
array('~\\\\.abc~', '\\\\@abc'), |
||||
array('~\\\\\\.abc~', '\\\\\\.abc'), |
||||
); |
||||
} |
||||
} |
||||
@ -1,57 +0,0 @@ |
||||
<?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\FakeAdapter; |
||||
|
||||
use Symfony\Component\Finder\Adapter\AbstractAdapter; |
||||
|
||||
/** |
||||
* @author Jean-François Simon <contact@jfsimon.fr> |
||||
*/ |
||||
class DummyAdapter extends AbstractAdapter |
||||
{ |
||||
/** |
||||
* @var \Iterator |
||||
*/ |
||||
private $iterator; |
||||
|
||||
/** |
||||
* @param \Iterator $iterator |
||||
*/ |
||||
public function __construct(\Iterator $iterator) |
||||
{ |
||||
$this->iterator = $iterator; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function searchInDirectory($dir) |
||||
{ |
||||
return $this->iterator; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getName() |
||||
{ |
||||
return 'yes'; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function canBeUsed() |
||||
{ |
||||
return true; |
||||
} |
||||
} |
||||
@ -1,45 +0,0 @@ |
||||
<?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\FakeAdapter; |
||||
|
||||
use Symfony\Component\Finder\Adapter\AbstractAdapter; |
||||
use Symfony\Component\Finder\Exception\AdapterFailureException; |
||||
|
||||
/** |
||||
* @author Jean-François Simon <contact@jfsimon.fr> |
||||
*/ |
||||
class FailingAdapter extends AbstractAdapter |
||||
{ |
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function searchInDirectory($dir) |
||||
{ |
||||
throw new AdapterFailureException($this); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getName() |
||||
{ |
||||
return 'failing'; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function canBeUsed() |
||||
{ |
||||
return true; |
||||
} |
||||
} |
||||
@ -1,57 +0,0 @@ |
||||
<?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\FakeAdapter; |
||||
|
||||
use Symfony\Component\Finder\Adapter\AbstractAdapter; |
||||
|
||||
/** |
||||
* @author Jean-François Simon <contact@jfsimon.fr> |
||||
*/ |
||||
class NamedAdapter extends AbstractAdapter |
||||
{ |
||||
/** |
||||
* @var string |
||||
*/ |
||||
private $name; |
||||
|
||||
/** |
||||
* @param string $name |
||||
*/ |
||||
public function __construct($name) |
||||
{ |
||||
$this->name = $name; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function searchInDirectory($dir) |
||||
{ |
||||
return new \ArrayIterator(array()); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getName() |
||||
{ |
||||
return $this->name; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function canBeUsed() |
||||
{ |
||||
return true; |
||||
} |
||||
} |
||||
@ -1,44 +0,0 @@ |
||||
<?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\FakeAdapter; |
||||
|
||||
use Symfony\Component\Finder\Adapter\AbstractAdapter; |
||||
|
||||
/** |
||||
* @author Jean-François Simon <contact@jfsimon.fr> |
||||
*/ |
||||
class UnsupportedAdapter extends AbstractAdapter |
||||
{ |
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function searchInDirectory($dir) |
||||
{ |
||||
return new \ArrayIterator(array()); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getName() |
||||
{ |
||||
return 'unsupported'; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function canBeUsed() |
||||
{ |
||||
return false; |
||||
} |
||||
} |
||||
@ -1,48 +0,0 @@ |
||||
<?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->getAbsolutePath(''), \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() |
||||
{ |
||||
return array( |
||||
array(0, 0, array($this->getAbsolutePath('/.git'), $this->getAbsolutePath('/test.py'), $this->getAbsolutePath('/foo'), $this->getAbsolutePath('/test.php'), $this->getAbsolutePath('/toto'), $this->getAbsolutePath('/.foo'), $this->getAbsolutePath('/.bar'), $this->getAbsolutePath('/foo bar'))), |
||||
array(0, 1, array($this->getAbsolutePath('/.git'), $this->getAbsolutePath('/test.py'), $this->getAbsolutePath('/foo'), $this->getAbsolutePath('/foo/bar.tmp'), $this->getAbsolutePath('/test.php'), $this->getAbsolutePath('/toto'), $this->getAbsolutePath('/.foo'), $this->getAbsolutePath('/.foo/.bar'), $this->getAbsolutePath('/.bar'), $this->getAbsolutePath('/foo bar'), $this->getAbsolutePath('/.foo/bar'))), |
||||
array(2, INF, array()), |
||||
array(1, INF, array($this->getAbsolutePath('/foo/bar.tmp'), $this->getAbsolutePath('/.foo/.bar'), $this->getAbsolutePath('/.foo/bar'))), |
||||
array(1, 1, array($this->getAbsolutePath('/foo/bar.tmp'), $this->getAbsolutePath('/.foo/.bar'), $this->getAbsolutePath('/.foo/bar'))), |
||||
); |
||||
} |
||||
|
||||
protected function getAbsolutePath($path) |
||||
{ |
||||
return sys_get_temp_dir().'/symfony2_finder'.str_replace('/', DIRECTORY_SEPARATOR, $path); |
||||
} |
||||
} |
||||
@ -0,0 +1,49 @@ |
||||
<?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; |
||||
use Symfony\Component\Finder\Comparator\NumberComparator; |
||||
|
||||
class DepthRangeFilterIteratorTest extends RealIteratorTestCase |
||||
{ |
||||
/** |
||||
* @dataProvider getAcceptData |
||||
*/ |
||||
public function testAccept($size, $expected) |
||||
{ |
||||
$inner = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->getAbsolutePath(''), \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST); |
||||
|
||||
$iterator = new DepthRangeFilterIterator($inner, $size); |
||||
|
||||
$actual = array_keys(iterator_to_array($iterator)); |
||||
sort($expected); |
||||
sort($actual); |
||||
$this->assertEquals($expected, $actual); |
||||
} |
||||
|
||||
public function getAcceptData() |
||||
{ |
||||
return array( |
||||
array(array(new NumberComparator('< 1')), array($this->getAbsolutePath('/.git'), $this->getAbsolutePath('/test.py'), $this->getAbsolutePath('/foo'), $this->getAbsolutePath('/test.php'), $this->getAbsolutePath('/toto'), $this->getAbsolutePath('/.foo'), $this->getAbsolutePath('/.bar'))), |
||||
array(array(new NumberComparator('<= 1')), array($this->getAbsolutePath('/.git'), $this->getAbsolutePath('/test.py'), $this->getAbsolutePath('/foo'), $this->getAbsolutePath('/foo/bar.tmp'), $this->getAbsolutePath('/test.php'), $this->getAbsolutePath('/toto'), $this->getAbsolutePath('/.foo'), $this->getAbsolutePath('/.foo/.bar'), $this->getAbsolutePath('/.bar'))), |
||||
array(array(new NumberComparator('> 1')), array()), |
||||
array(array(new NumberComparator('>= 1')), array($this->getAbsolutePath('/foo/bar.tmp'), $this->getAbsolutePath('/.foo/.bar'))), |
||||
array(array(new NumberComparator('1')), array($this->getAbsolutePath('/foo/bar.tmp'), $this->getAbsolutePath('/.foo/.bar'))), |
||||
); |
||||
} |
||||
|
||||
protected function getAbsolutePath($path) |
||||
{ |
||||
return sys_get_temp_dir().'/symfony2_finder'.str_replace('/', DIRECTORY_SEPARATOR, $path); |
||||
} |
||||
} |
||||
@ -1,66 +0,0 @@ |
||||
<?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\FilePathsIterator; |
||||
|
||||
class FilePathsIteratorTest extends RealIteratorTestCase |
||||
{ |
||||
/** |
||||
* @dataProvider getSubPathData |
||||
*/ |
||||
public function testSubPath($baseDir, array $paths, array $subPaths, array $subPathnames) |
||||
{ |
||||
$iterator = new FilePathsIterator($paths, $baseDir); |
||||
|
||||
foreach ($iterator as $index => $file) { |
||||
$this->assertEquals($paths[$index], $file->getPathname()); |
||||
$this->assertEquals($subPaths[$index], $iterator->getSubPath()); |
||||
$this->assertEquals($subPathnames[$index], $iterator->getSubPathname()); |
||||
} |
||||
} |
||||
|
||||
public function getSubPathData() |
||||
{ |
||||
$tmpDir = sys_get_temp_dir().'/symfony2_finder'; |
||||
|
||||
return array( |
||||
array( |
||||
$tmpDir, |
||||
array( // paths |
||||
$tmpDir.DIRECTORY_SEPARATOR.'.git' => $tmpDir.DIRECTORY_SEPARATOR.'.git', |
||||
$tmpDir.DIRECTORY_SEPARATOR.'test.py' => $tmpDir.DIRECTORY_SEPARATOR.'test.py', |
||||
$tmpDir.DIRECTORY_SEPARATOR.'foo' => $tmpDir.DIRECTORY_SEPARATOR.'foo', |
||||
$tmpDir.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'bar.tmp' => $tmpDir.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'bar.tmp', |
||||
$tmpDir.DIRECTORY_SEPARATOR.'test.php' => $tmpDir.DIRECTORY_SEPARATOR.'test.php', |
||||
$tmpDir.DIRECTORY_SEPARATOR.'toto' => $tmpDir.DIRECTORY_SEPARATOR.'toto' |
||||
), |
||||
array( // subPaths |
||||
$tmpDir.DIRECTORY_SEPARATOR.'.git' => '', |
||||
$tmpDir.DIRECTORY_SEPARATOR.'test.py' => '', |
||||
$tmpDir.DIRECTORY_SEPARATOR.'foo' => '', |
||||
$tmpDir.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'bar.tmp' => 'foo', |
||||
$tmpDir.DIRECTORY_SEPARATOR.'test.php' => '', |
||||
$tmpDir.DIRECTORY_SEPARATOR.'toto' => '' |
||||
), |
||||
array( // subPathnames |
||||
$tmpDir.DIRECTORY_SEPARATOR.'.git' => '.git', |
||||
$tmpDir.DIRECTORY_SEPARATOR.'test.py' => 'test.py', |
||||
$tmpDir.DIRECTORY_SEPARATOR.'foo' => 'foo', |
||||
$tmpDir.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'bar.tmp' => 'foo'.DIRECTORY_SEPARATOR.'bar.tmp', |
||||
$tmpDir.DIRECTORY_SEPARATOR.'test.php' => 'test.php', |
||||
$tmpDir.DIRECTORY_SEPARATOR.'toto' => 'toto' |
||||
), |
||||
), |
||||
); |
||||
} |
||||
} |
||||
@ -1,21 +0,0 @@ |
||||
<?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); |
||||
} |
||||
} |
||||
@ -1,134 +0,0 @@ |
||||
<?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 ($this->type === null) { |
||||
return preg_match('/file/', $this->getFilename()); |
||||
}; |
||||
|
||||
return self::TYPE_FILE === $this->type; |
||||
} |
||||
|
||||
public function isDir() |
||||
{ |
||||
if ($this->type === null) { |
||||
return preg_match('/directory/', $this->getFilename()); |
||||
} |
||||
|
||||
return self::TYPE_DIRECTORY === $this->type; |
||||
} |
||||
|
||||
public function isReadable() |
||||
{ |
||||
if ($this->mode === null) { |
||||
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': |
||||
$this->type = self::TYPE_DIRECTORY; |
||||
case 'd': |
||||
$this->type = self::TYPE_DIRECTORY; |
||||
break; |
||||
case 'file': |
||||
$this->type = self::TYPE_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; |
||||
} |
||||
} |
||||
@ -1,85 +0,0 @@ |
||||
<?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')), |
||||
|
||||
); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,18 @@ |
||||
<?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. |
||||
*/ |
||||
|
||||
spl_autoload_register(function ($class) { |
||||
if (0 === strpos(ltrim($class, '/'), 'Symfony\Component\Finder')) { |
||||
if (file_exists($file = __DIR__.'/../'.substr(str_replace('\\', '/', $class), strlen('Symfony\Component\Finder')).'.php')) { |
||||
require_once $file; |
||||
} |
||||
} |
||||
}); |
||||
Loading…
Reference in new issue