merged branch vicb/finder-adapters (PR #6253)

This PR was squashed before being merged into the master branch (closes #6253).

Commits
-------

e62b5f7 [Finder] cleanup, fixes, improvements

Discussion
----------

[Finder] cleanup, fixes, improvements
This commit is contained in:
Fabien Potencier 2012-12-10 14:52:40 +01:00
commit 1ec59f174e
12 changed files with 198 additions and 167 deletions

View File

@ -34,6 +34,22 @@ abstract class AbstractAdapter implements AdapterInterface
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}
*/
@ -193,4 +209,17 @@ abstract class AbstractAdapter implements AdapterInterface
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();
}

View File

@ -59,11 +59,11 @@ abstract class AbstractFindAdapter extends AbstractAdapter
$find->add('-follow');
}
$find->add('-mindepth')->add($this->minDepth+1);
$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);
$find->add('-maxdepth')->add($this->maxDepth + 1);
}
if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode) {
@ -118,13 +118,14 @@ abstract class AbstractFindAdapter extends AbstractAdapter
/**
* {@inheritdoc}
*/
public function isSupported()
protected function canBeUsed()
{
return $this->shell->testCommand('find');
}
/**
* @param Command $command
* @param string $dir
*
* @return Command
*/
@ -140,7 +141,7 @@ abstract class AbstractFindAdapter extends AbstractAdapter
/**
* @param Command $command
* @param string[] $names
* @param bool $not
* @param Boolean $not
*/
private function buildNamesFiltering(Command $command, array $names, $not = false)
{
@ -183,7 +184,8 @@ abstract class AbstractFindAdapter extends AbstractAdapter
* @param Command $command
* @param string $dir
* @param string[] $paths
* @param bool $not
* @param Boolean $not
*
* @return void
*/
private function buildPathsFiltering(Command $command, $dir, array $paths, $not = false)
@ -226,33 +228,23 @@ abstract class AbstractFindAdapter extends AbstractAdapter
foreach ($sizes as $i => $size) {
$command->add($i > 0 ? '-and' : null);
if ('<=' === $size->getOperator()) {
$command->add('-size -'.($size->getTarget()+1).'c');
continue;
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');
}
if ('<' === $size->getOperator()) {
$command->add('-size -'.$size->getTarget().'c');
continue;
}
if ('>=' === $size->getOperator()) {
$command->add('-size +'.($size->getTarget()-1).'c');
continue;
}
if ('>' === $size->getOperator()) {
$command->add('-size +'.$size->getTarget().'c');
continue;
}
if ('!=' === $size->getOperator()) {
$command->add('-size -'.$size->getTarget().'c');
$command->add('-size +'.$size->getTarget().'c');
continue;
}
$command->add('-size '.$size->getTarget().'c');
}
}
@ -265,7 +257,7 @@ abstract class AbstractFindAdapter extends AbstractAdapter
foreach ($dates as $i => $date) {
$command->add($i > 0 ? '-and' : null);
$mins = (int) round((time()-$date->getTarget())/60);
$mins = (int) round((time()-$date->getTarget()) / 60);
if (0 > $mins) {
// mtime is in the future
@ -274,39 +266,30 @@ abstract class AbstractFindAdapter extends AbstractAdapter
return;
}
if ('<=' === $date->getOperator()) {
$command->add('-mmin +'.($mins-1));
continue;
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);
}
if ('<' === $date->getOperator()) {
$command->add('-mmin +'.$mins);
continue;
}
if ('>=' === $date->getOperator()) {
$command->add('-mmin -'.($mins+1));
continue;
}
if ('>' === $date->getOperator()) {
$command->add('-mmin -'.$mins);
continue;
}
if ('!=' === $date->getOperator()) {
$command->add('-mmin +'.$mins.' -or -mmin -'.$mins);
continue;
}
$command->add('-mmin '.$mins);
}
}
/**
* @param Command $command
* @param array $contains
* @param bool $not
* @param Boolean $not
*/
private function buildContentFiltering(Command $command, array $contains, $not = false)
{
@ -323,8 +306,9 @@ abstract class AbstractFindAdapter extends AbstractAdapter
}
/**
* @param \Symfony\Component\Finder\Shell\Command $command
* @param string $sort
* @param Command $command
* @param string $sort
*
* @throws \InvalidArgumentException
*/
private function buildSorting(Command $command, $sort)

View File

@ -17,14 +17,14 @@ namespace Symfony\Component\Finder\Adapter;
interface AdapterInterface
{
/**
* @param bool $followLinks
* @param Boolean $followLinks
*
* @return AdapterInterface Current instance
*/
public function setFollowLinks($followLinks);
/**
* @param int $mode
* @param integer $mode
*
* @return AdapterInterface Current instance
*/
@ -94,14 +94,14 @@ interface AdapterInterface
public function setFilters(array $filters);
/**
* @param \Closure|int $sort
* @param \Closure|integer $sort
*
* @return AdapterInterface Current instance
*/
public function setSort($sort);
/**
* @param array $path
* @param array $paths
*
* @return AdapterInterface Current instance
*/
@ -124,7 +124,7 @@ interface AdapterInterface
/**
* Tests adapter support for current platform.
*
* @return bool
* @return Boolean
*/
public function isSupported();

View File

@ -22,14 +22,6 @@ use Symfony\Component\Finder\Shell\Command;
*/
class BsdFindAdapter extends AbstractFindAdapter
{
/**
* {@inheritdoc}
*/
public function isSupported()
{
return in_array($this->shell->getType(), array(Shell::TYPE_BSD, Shell::TYPE_DARWIN)) && parent::isSupported();
}
/**
* {@inheritdoc}
*/
@ -38,12 +30,25 @@ class BsdFindAdapter extends AbstractFindAdapter
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, $format)
{
$command->get('find')->add('-print0 | xargs -0 stat -f')->arg($format.' %h/%f\\n')
->add('| sort | cut')->arg('-d ')->arg('-f2-');
$command
->get('find')
->add('-print0 | xargs -0 stat -f')
->arg($format.' %h/%f\\n')
->add('| sort | cut')
->arg('-d ')
->arg('-f2-');
}
}

View File

@ -22,14 +22,6 @@ use Symfony\Component\Finder\Shell\Command;
*/
class GnuFindAdapter extends AbstractFindAdapter
{
/**
* {@inheritdoc}
*/
public function isSupported()
{
return $this->shell->getType() === Shell::TYPE_UNIX && parent::isSupported();
}
/**
* {@inheritdoc}
*/
@ -43,8 +35,22 @@ class GnuFindAdapter extends AbstractFindAdapter
*/
protected function buildFormatSorting(Command $command, $format)
{
$command->get('find')->add('-printf')->arg($format.' %h/%f\\n')
->add('| sort | cut')->arg('-d ')->arg('-f2-');
$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();
}
/**

View File

@ -83,16 +83,16 @@ class PhpAdapter extends AbstractAdapter
/**
* {@inheritdoc}
*/
public function isSupported()
public function getName()
{
return true;
return 'php';
}
/**
* {@inheritdoc}
*/
public function getName()
protected function canBeUsed()
{
return 'php';
return true;
}
}

View File

@ -65,9 +65,11 @@ class Finder implements \IteratorAggregate, \Countable
{
$this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES;
$this->addAdapter(new GnuFindAdapter());
$this->addAdapter(new BsdFindAdapter());
$this->addAdapter(new PhpAdapter(), -50);
$this
->addAdapter(new GnuFindAdapter())
->addAdapter(new BsdFindAdapter())
->addAdapter(new PhpAdapter(), -50)
;
}
/**
@ -86,7 +88,7 @@ class Finder implements \IteratorAggregate, \Countable
* Registers a finder engine implementation.
*
* @param AdapterInterface $adapter An adapter instance
* @param int $priority Highest is selected first
* @param integer $priority Highest is selected first
*
* @return Finder The current Finder instance
*/
@ -418,9 +420,20 @@ class Finder implements \IteratorAggregate, \Countable
return $this;
}
/**
* Adds VCS patterns.
*
* @see ignoreVCS
*
* @param string|string[] $pattern VCS patterns to ignore
*/
public static function addVCSPattern($pattern)
{
self::$vcsPatterns[] = $pattern;
foreach ((array) $pattern as $p) {
self::$vcsPatterns[] = $p;
}
self::$vcsPatterns = array_unique(self::$vcsPatterns);
}
/**
@ -691,6 +704,8 @@ class Finder implements \IteratorAggregate, \Countable
* @param $dir
*
* @return \Iterator
*
* @throws \RuntimeException When none of the adapters are supported
*/
private function searchInDirectory($dir)
{
@ -703,16 +718,12 @@ class Finder implements \IteratorAggregate, \Countable
}
foreach ($this->adapters as $adapter) {
if (!$adapter['adapter']->isSupported()) {
continue;
}
try {
return $this
->buildAdapter($adapter['adapter'])
->searchInDirectory($dir);
} catch(ExceptionInterface $e) {
continue;
if ($adapter['adapter']->isSupported()) {
try {
return $this
->buildAdapter($adapter['adapter'])
->searchInDirectory($dir);
} catch(ExceptionInterface $e) {}
}
}

View File

@ -42,16 +42,16 @@ class DummyAdapter extends AbstractAdapter
/**
* {@inheritdoc}
*/
public function isSupported()
public function getName()
{
return true;
return 'yes';
}
/**
* {@inheritdoc}
*/
public function getName()
protected function canBeUsed()
{
return 'yes';
return true;
}
}

View File

@ -30,16 +30,16 @@ class FailingAdapter extends AbstractAdapter
/**
* {@inheritdoc}
*/
public function isSupported()
public function getName()
{
return true;
return 'failing';
}
/**
* {@inheritdoc}
*/
function getName()
protected function canBeUsed()
{
return 'failing';
return true;
}
}

View File

@ -42,16 +42,16 @@ class NamedAdapter extends AbstractAdapter
/**
* {@inheritdoc}
*/
public function isSupported()
public function getName()
{
return true;
return $this->name;
}
/**
* {@inheritdoc}
*/
function getName()
protected function canBeUsed()
{
return $this->name;
return true;
}
}

View File

@ -29,16 +29,16 @@ class UnsupportedAdapter extends AbstractAdapter
/**
* {@inheritdoc}
*/
public function isSupported()
public function getName()
{
return false;
return 'unsupported';
}
/**
* {@inheritdoc}
*/
function getName()
protected function canBeUsed()
{
return 'unsupported';
return false;
}
}

View File

@ -356,9 +356,7 @@ class FinderTest extends Iterator\RealIteratorTestCase
*/
public function testRelativePath($adapter)
{
$finder = $this->buildFinder($adapter);
$finder->in(self::$tmpDir);
$finder = $this->buildFinder($adapter)->in(self::$tmpDir);
$paths = array();
@ -379,9 +377,7 @@ class FinderTest extends Iterator\RealIteratorTestCase
*/
public function testRelativePathname($adapter)
{
$finder = $this->buildFinder($adapter);
$finder->in(self::$tmpDir)->sortByName();
$finder = $this->buildFinder($adapter)->in(self::$tmpDir)->sortByName();
$paths = array();
@ -450,8 +446,7 @@ class FinderTest extends Iterator\RealIteratorTestCase
public function testCountDirectories()
{
$finder = new Finder();
$directory = $finder->directories()->in(self::$tmpDir);
$directory = Finder::create()->directories()->in(self::$tmpDir);
$i = 0;
foreach ($directory as $dir) {
@ -463,8 +458,7 @@ class FinderTest extends Iterator\RealIteratorTestCase
public function testCountFiles()
{
$finder = new Finder();
$files = $finder->files()->in(__DIR__.DIRECTORY_SEPARATOR.'Fixtures');
$files = Finder::create()->files()->in(__DIR__.DIRECTORY_SEPARATOR.'Fixtures');
$i = 0;
foreach ($files as $file) {
@ -474,17 +468,13 @@ class FinderTest extends Iterator\RealIteratorTestCase
$this->assertCount($i, $files);
}
/**
* @expectedException \LogicException
*/
public function testCountWithoutIn()
{
$finder = new Finder();
$finder->files();
try {
count($finder);
$this->fail('Countable makes use of the getIterator command');
} catch (\Exception $e) {
$this->assertInstanceOf('LogicException', $e, '->getIterator() throws \LogicException when no logic has been entered');
}
$finder = Finder::create()->files();
count($finder);
}
protected function toAbsolute($files)
@ -641,37 +631,10 @@ class FinderTest extends Iterator\RealIteratorTestCase
return $this->buildTestData($tests);
}
private function buildFinder(Adapter\AdapterInterface $adapter)
{
return Finder::create()
->removeAdapters()
->addAdapter($adapter);
}
private function getValidAdapters()
{
return array_filter(
array(new Adapter\GnuFindAdapter(), new Adapter\PhpAdapter()),
function (Adapter\AdapterInterface $adapter) { return $adapter->isSupported(); }
);
}
private function buildTestData(array $tests)
{
$data = array();
foreach ($this->getValidAdapters() as $adapter) {
foreach ($tests as $test) {
$data[] = array_merge(array($adapter), $test);
}
}
return $data;
}
/**
* @dataProvider getTestPathData
*/
public function testPath(Adapter\AdapterInterface $adapter, $matchPatterns, $noMatchPatterns, $expected)
public function testPath(Adapter\AdapterInterface $adapter, $matchPatterns, $noMatchPatterns, array $expected)
{
$finder = $this->buildFinder($adapter);
$finder->in(__DIR__.DIRECTORY_SEPARATOR.'Fixtures')
@ -722,4 +685,37 @@ class FinderTest extends Iterator\RealIteratorTestCase
return $this->buildTestData($tests);
}
private function buildTestData(array $tests)
{
$data = array();
foreach ($this->getValidAdapters() as $adapter) {
foreach ($tests as $test) {
$data[] = array_merge(array($adapter), $test);
}
}
return $data;
}
private function buildFinder(Adapter\AdapterInterface $adapter)
{
return Finder::create()
->removeAdapters()
->addAdapter($adapter);
}
private function getValidAdapters()
{
return array_filter(
array(
new Adapter\BsdFindAdapter(),
new Adapter\GnuFindAdapter(),
new Adapter\PhpAdapter()
),
function (Adapter\AdapterInterface $adapter) {
return $adapter->isSupported();
}
);
}
}