[Finder] added Finder::ignoreUnreadableDirs() method
This commit is contained in:
parent
ea79360fba
commit
a63b30b5ce
@ -33,6 +33,7 @@ abstract class AbstractAdapter implements AdapterInterface
|
|||||||
protected $sort = false;
|
protected $sort = false;
|
||||||
protected $paths = array();
|
protected $paths = array();
|
||||||
protected $notPaths = array();
|
protected $notPaths = array();
|
||||||
|
protected $ignoreUnreadableDirs = false;
|
||||||
|
|
||||||
private static $areSupported = array();
|
private static $areSupported = array();
|
||||||
|
|
||||||
@ -210,6 +211,16 @@ abstract class AbstractAdapter implements AdapterInterface
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function ignoreUnreadableDirs($ignore = true)
|
||||||
|
{
|
||||||
|
$this->ignoreUnreadableDirs = (Boolean) $ignore;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the adapter is supported in the current environment.
|
* Returns whether the adapter is supported in the current environment.
|
||||||
*
|
*
|
||||||
|
@ -92,9 +92,12 @@ abstract class AbstractFindAdapter extends AbstractAdapter
|
|||||||
$this->buildSorting($command, $this->sort);
|
$this->buildSorting($command, $this->sort);
|
||||||
}
|
}
|
||||||
|
|
||||||
$command->setErrorHandler(function ($stderr) {
|
$command->setErrorHandler(
|
||||||
throw new AccessDeniedException($stderr);
|
$this->ignoreUnreadableDirs
|
||||||
});
|
// If directory is unreadable and finder is set to ignore it, `stderr` is ignored.
|
||||||
|
? function ($stderr) { return; }
|
||||||
|
: function ($stderr) { throw new AccessDeniedException($stderr); }
|
||||||
|
);
|
||||||
|
|
||||||
$paths = $this->shell->testCommand('uniq') ? $command->add('| uniq')->execute() : array_unique($command->execute());
|
$paths = $this->shell->testCommand('uniq') ? $command->add('| uniq')->execute() : array_unique($command->execute());
|
||||||
$iterator = new Iterator\FilePathsIterator($paths, $dir);
|
$iterator = new Iterator\FilePathsIterator($paths, $dir);
|
||||||
|
@ -114,6 +114,13 @@ interface AdapterInterface
|
|||||||
*/
|
*/
|
||||||
public function setNotPath(array $notPaths);
|
public function setNotPath(array $notPaths);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param boolean $ignore
|
||||||
|
*
|
||||||
|
* @return AdapterInterface Current instance
|
||||||
|
*/
|
||||||
|
public function ignoreUnreadableDirs($ignore = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $dir
|
* @param string $dir
|
||||||
*
|
*
|
||||||
|
@ -32,7 +32,7 @@ class PhpAdapter extends AbstractAdapter
|
|||||||
}
|
}
|
||||||
|
|
||||||
$iterator = new \RecursiveIteratorIterator(
|
$iterator = new \RecursiveIteratorIterator(
|
||||||
new Iterator\RecursiveDirectoryIterator($dir, $flags),
|
new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs),
|
||||||
\RecursiveIteratorIterator::SELF_FIRST
|
\RecursiveIteratorIterator::SELF_FIRST
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -55,6 +55,7 @@ class Finder implements \IteratorAggregate, \Countable
|
|||||||
private $adapters = array();
|
private $adapters = array();
|
||||||
private $paths = array();
|
private $paths = array();
|
||||||
private $notPaths = array();
|
private $notPaths = array();
|
||||||
|
private $ignoreUnreadableDirs = false;
|
||||||
|
|
||||||
private static $vcsPatterns = array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg');
|
private static $vcsPatterns = array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg');
|
||||||
|
|
||||||
@ -626,6 +627,22 @@ class Finder implements \IteratorAggregate, \Countable
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells finder to ignore unreadable directories.
|
||||||
|
*
|
||||||
|
* By default, scanning unreadable directories content throws an AccessDeniedException.
|
||||||
|
*
|
||||||
|
* @param boolean $ignore
|
||||||
|
*
|
||||||
|
* @return Finder The current Finder instance
|
||||||
|
*/
|
||||||
|
public function ignoreUnreadableDirs($ignore = true)
|
||||||
|
{
|
||||||
|
$this->ignoreUnreadableDirs = (Boolean) $ignore;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Searches files and directories which match defined rules.
|
* Searches files and directories which match defined rules.
|
||||||
*
|
*
|
||||||
@ -794,7 +811,8 @@ class Finder implements \IteratorAggregate, \Countable
|
|||||||
->setFilters($this->filters)
|
->setFilters($this->filters)
|
||||||
->setSort($this->sort)
|
->setSort($this->sort)
|
||||||
->setPath($this->paths)
|
->setPath($this->paths)
|
||||||
->setNotPath($this->notPaths);
|
->setNotPath($this->notPaths)
|
||||||
|
->ignoreUnreadableDirs($this->ignoreUnreadableDirs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -21,13 +21,28 @@ use Symfony\Component\Finder\SplFileInfo;
|
|||||||
*/
|
*/
|
||||||
class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
|
class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
|
||||||
{
|
{
|
||||||
public function __construct($path, $flags)
|
/**
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
private $ignoreUnreadableDirs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param string $path
|
||||||
|
* @param int $flags
|
||||||
|
* @param boolean $ignoreUnreadableDirs
|
||||||
|
*
|
||||||
|
* @throws \RuntimeException
|
||||||
|
*/
|
||||||
|
public function __construct($path, $flags, $ignoreUnreadableDirs = false)
|
||||||
{
|
{
|
||||||
if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) {
|
if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) {
|
||||||
throw new \RuntimeException('This iterator only support returning current as fileinfo.');
|
throw new \RuntimeException('This iterator only support returning current as fileinfo.');
|
||||||
}
|
}
|
||||||
|
|
||||||
parent::__construct($path, $flags);
|
parent::__construct($path, $flags);
|
||||||
|
$this->ignoreUnreadableDirs = $ignoreUnreadableDirs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -41,7 +56,7 @@ class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return mixed object
|
* @return \RecursiveIterator
|
||||||
*
|
*
|
||||||
* @throws AccessDeniedException
|
* @throws AccessDeniedException
|
||||||
*/
|
*/
|
||||||
@ -50,7 +65,12 @@ class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
|
|||||||
try {
|
try {
|
||||||
return parent::getChildren();
|
return parent::getChildren();
|
||||||
} catch (\UnexpectedValueException $e) {
|
} catch (\UnexpectedValueException $e) {
|
||||||
throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e);
|
if ($this->ignoreUnreadableDirs) {
|
||||||
|
// If directory is unreadable and finder is set to ignore it, a fake empty content is returned.
|
||||||
|
return new \RecursiveArrayIterator(array());
|
||||||
|
} else {
|
||||||
|
throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -725,16 +725,34 @@ class FinderTest extends Iterator\RealIteratorTestCase
|
|||||||
$finder = $this->buildFinder($adapter);
|
$finder = $this->buildFinder($adapter);
|
||||||
$finder->files()->in(self::$tmpDir);
|
$finder->files()->in(self::$tmpDir);
|
||||||
|
|
||||||
// make 'foo' directory non-openable
|
// make 'foo' directory non-readable
|
||||||
chmod(self::$tmpDir.DIRECTORY_SEPARATOR.'foo', 0333);
|
chmod(self::$tmpDir.DIRECTORY_SEPARATOR.'foo', 0333);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->getIterator());
|
$this->assertIterator($this->toAbsolute(array('foo bar', 'test.php', 'test.py')), $finder->getIterator());
|
||||||
$this->fail('Finder should throw an exception when opening a non-readable directory.');
|
$this->fail('Finder should throw an exception when opening a non-readable directory.');
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$this->assertEquals('Symfony\\Component\\Finder\\Exception\\AccessDeniedException', get_class($e));
|
$this->assertEquals('Symfony\\Component\\Finder\\Exception\\AccessDeniedException', get_class($e));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// restore original permissions
|
||||||
|
chmod(self::$tmpDir.DIRECTORY_SEPARATOR.'foo', 0777);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider getAdaptersTestData
|
||||||
|
*/
|
||||||
|
public function testIgnoredAccessDeniedException(Adapter\AdapterInterface $adapter)
|
||||||
|
{
|
||||||
|
$finder = $this->buildFinder($adapter);
|
||||||
|
$finder->files()->ignoreUnreadableDirs()->in(self::$tmpDir);
|
||||||
|
|
||||||
|
// make 'foo' directory non-readable
|
||||||
|
chmod(self::$tmpDir.DIRECTORY_SEPARATOR.'foo', 0333);
|
||||||
|
|
||||||
|
$this->assertIterator($this->toAbsolute(array('foo bar', 'test.php', 'test.py')), $finder->getIterator());
|
||||||
|
|
||||||
|
// restore original permissions
|
||||||
chmod(self::$tmpDir.DIRECTORY_SEPARATOR.'foo', 0777);
|
chmod(self::$tmpDir.DIRECTORY_SEPARATOR.'foo', 0777);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user