From e62b5f78afeecf2896ea1bbfc773b56fee7e1c38 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Mon, 10 Dec 2012 09:50:12 +0100 Subject: [PATCH] [Finder] cleanup, fixes, improvements --- .../Finder/Adapter/AbstractAdapter.php | 29 +++++ .../Finder/Adapter/AbstractFindAdapter.php | 104 ++++++++---------- .../Finder/Adapter/AdapterInterface.php | 10 +- .../Finder/Adapter/BsdFindAdapter.php | 25 +++-- .../Finder/Adapter/GnuFindAdapter.php | 26 +++-- .../Component/Finder/Adapter/PhpAdapter.php | 8 +- src/Symfony/Component/Finder/Finder.php | 41 ++++--- .../Finder/Tests/FakeAdapter/DummyAdapter.php | 8 +- .../Tests/FakeAdapter/FailingAdapter.php | 8 +- .../Finder/Tests/FakeAdapter/NamedAdapter.php | 8 +- .../Tests/FakeAdapter/UnsupportedAdapter.php | 8 +- .../Component/Finder/Tests/FinderTest.php | 90 ++++++++------- 12 files changed, 198 insertions(+), 167 deletions(-) diff --git a/src/Symfony/Component/Finder/Adapter/AbstractAdapter.php b/src/Symfony/Component/Finder/Adapter/AbstractAdapter.php index 38ac2835fd..839a601638 100644 --- a/src/Symfony/Component/Finder/Adapter/AbstractAdapter.php +++ b/src/Symfony/Component/Finder/Adapter/AbstractAdapter.php @@ -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(); } diff --git a/src/Symfony/Component/Finder/Adapter/AbstractFindAdapter.php b/src/Symfony/Component/Finder/Adapter/AbstractFindAdapter.php index 9cde873a64..d60fbaa222 100644 --- a/src/Symfony/Component/Finder/Adapter/AbstractFindAdapter.php +++ b/src/Symfony/Component/Finder/Adapter/AbstractFindAdapter.php @@ -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) diff --git a/src/Symfony/Component/Finder/Adapter/AdapterInterface.php b/src/Symfony/Component/Finder/Adapter/AdapterInterface.php index 829297b3ec..f28ffb3189 100644 --- a/src/Symfony/Component/Finder/Adapter/AdapterInterface.php +++ b/src/Symfony/Component/Finder/Adapter/AdapterInterface.php @@ -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(); diff --git a/src/Symfony/Component/Finder/Adapter/BsdFindAdapter.php b/src/Symfony/Component/Finder/Adapter/BsdFindAdapter.php index 12f2f69768..53adc1f4e6 100644 --- a/src/Symfony/Component/Finder/Adapter/BsdFindAdapter.php +++ b/src/Symfony/Component/Finder/Adapter/BsdFindAdapter.php @@ -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-'); } } diff --git a/src/Symfony/Component/Finder/Adapter/GnuFindAdapter.php b/src/Symfony/Component/Finder/Adapter/GnuFindAdapter.php index bd903581d2..ac741745ff 100644 --- a/src/Symfony/Component/Finder/Adapter/GnuFindAdapter.php +++ b/src/Symfony/Component/Finder/Adapter/GnuFindAdapter.php @@ -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(); } /** diff --git a/src/Symfony/Component/Finder/Adapter/PhpAdapter.php b/src/Symfony/Component/Finder/Adapter/PhpAdapter.php index 3607165f9b..dfc842f6b5 100644 --- a/src/Symfony/Component/Finder/Adapter/PhpAdapter.php +++ b/src/Symfony/Component/Finder/Adapter/PhpAdapter.php @@ -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; } } diff --git a/src/Symfony/Component/Finder/Finder.php b/src/Symfony/Component/Finder/Finder.php index cbaa9acaa3..88d2198e15 100644 --- a/src/Symfony/Component/Finder/Finder.php +++ b/src/Symfony/Component/Finder/Finder.php @@ -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); } /** @@ -685,6 +698,8 @@ class Finder implements \IteratorAggregate, \Countable * @param $dir * * @return \Iterator + * + * @throws \RuntimeException When none of the adapters are supported */ private function searchInDirectory($dir) { @@ -697,16 +712,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) {} } } diff --git a/src/Symfony/Component/Finder/Tests/FakeAdapter/DummyAdapter.php b/src/Symfony/Component/Finder/Tests/FakeAdapter/DummyAdapter.php index c7143bfd76..0cbae14b88 100644 --- a/src/Symfony/Component/Finder/Tests/FakeAdapter/DummyAdapter.php +++ b/src/Symfony/Component/Finder/Tests/FakeAdapter/DummyAdapter.php @@ -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; } } diff --git a/src/Symfony/Component/Finder/Tests/FakeAdapter/FailingAdapter.php b/src/Symfony/Component/Finder/Tests/FakeAdapter/FailingAdapter.php index 00fc022fdf..6e6ed24b61 100644 --- a/src/Symfony/Component/Finder/Tests/FakeAdapter/FailingAdapter.php +++ b/src/Symfony/Component/Finder/Tests/FakeAdapter/FailingAdapter.php @@ -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; } } diff --git a/src/Symfony/Component/Finder/Tests/FakeAdapter/NamedAdapter.php b/src/Symfony/Component/Finder/Tests/FakeAdapter/NamedAdapter.php index 2321195e94..5a260b0dfc 100644 --- a/src/Symfony/Component/Finder/Tests/FakeAdapter/NamedAdapter.php +++ b/src/Symfony/Component/Finder/Tests/FakeAdapter/NamedAdapter.php @@ -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; } } diff --git a/src/Symfony/Component/Finder/Tests/FakeAdapter/UnsupportedAdapter.php b/src/Symfony/Component/Finder/Tests/FakeAdapter/UnsupportedAdapter.php index d02a13e032..1f91b98a60 100644 --- a/src/Symfony/Component/Finder/Tests/FakeAdapter/UnsupportedAdapter.php +++ b/src/Symfony/Component/Finder/Tests/FakeAdapter/UnsupportedAdapter.php @@ -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; } } diff --git a/src/Symfony/Component/Finder/Tests/FinderTest.php b/src/Symfony/Component/Finder/Tests/FinderTest.php index 9b8384b5cc..21604d896e 100644 --- a/src/Symfony/Component/Finder/Tests/FinderTest.php +++ b/src/Symfony/Component/Finder/Tests/FinderTest.php @@ -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(); @@ -428,8 +424,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) { @@ -441,8 +436,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) { @@ -452,17 +446,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) @@ -619,37 +609,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') @@ -700,4 +663,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(); + } + ); + } }