merged branch jfsimon/finder-access-denied-exception (PR #7256)

This PR was merged into the master branch.

Discussion
----------

[Finder] Adds AccessDeniedException

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | yes
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #6981

Commits
-------

714ace8 [finder] Introduced AccessDeniedException
This commit is contained in:
Fabien Potencier 2013-03-23 08:39:29 +01:00
commit e5be0ded50
5 changed files with 86 additions and 3 deletions

View File

@ -11,6 +11,7 @@
namespace Symfony\Component\Finder\Adapter;
use Symfony\Component\Finder\Exception\AccessDeniedException;
use Symfony\Component\Finder\Iterator;
use Symfony\Component\Finder\Shell\Shell;
use Symfony\Component\Finder\Expression\Expression;
@ -91,6 +92,10 @@ abstract class AbstractFindAdapter extends AbstractAdapter
$this->buildSorting($command, $this->sort);
}
$command->setErrorHandler(function ($stderr) {
throw new AccessDeniedException($stderr);
});
$paths = $this->shell->testCommand('uniq') ? $command->add('| uniq')->execute() : array_unique($command->execute());
$iterator = new Iterator\FilePathsIterator($paths, $dir);

View File

@ -0,0 +1,10 @@
<?php
namespace Symfony\Component\Finder\Exception;
/**
* @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
*/
class AccessDeniedException extends \UnexpectedValueException
{
}

View File

@ -11,6 +11,7 @@
namespace Symfony\Component\Finder\Iterator;
use Symfony\Component\Finder\Exception\AccessDeniedException;
use Symfony\Component\Finder\SplFileInfo;
/**
@ -38,4 +39,18 @@ class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
{
return new SplFileInfo(parent::current()->getPathname(), $this->getSubPath(), $this->getSubPathname());
}
/**
* @return mixed object
*
* @throws AccessDeniedException
*/
public function getChildren()
{
try {
return parent::getChildren();
} catch (\UnexpectedValueException $e) {
throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e);
}
}
}

View File

@ -31,6 +31,11 @@ class Command
*/
private $labels;
/**
* @var \Closure|null
*/
private $errorHandler;
/**
* Constructor.
*
@ -214,6 +219,26 @@ class Command
return count($this->bits);
}
/**
* @param \Closure $errorHandler
*
* @return Command
*/
public function setErrorHandler(\Closure $errorHandler)
{
$this->errorHandler = $errorHandler;
return $this;
}
/**
* @return callable|null
*/
public function getErrorHandler()
{
return $this->errorHandler;
}
/**
* Executes current command.
*
@ -223,10 +248,17 @@ class Command
*/
public function execute()
{
exec($this->join(), $output, $code);
if (null === $this->errorHandler) {
exec($this->join(), $output);
} else {
$process = proc_open($this->join(), array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $pipes);
$output = preg_split('~(\r\n|\r|\n)~', stream_get_contents($pipes[1]), -1, PREG_SPLIT_NO_EMPTY);
if (0 !== $code) {
throw new \RuntimeException('Execution failed with return code: '.$code.'.');
if ($error = stream_get_contents($pipes[2])) {
call_user_func($this->errorHandler, $error);
}
proc_close($process);
}
return $output ?: array();

View File

@ -717,6 +717,27 @@ class FinderTest extends Iterator\RealIteratorTestCase
return $this->buildTestData($tests);
}
/**
* @dataProvider getAdaptersTestData
*/
public function testAccessDeniedException(Adapter\AdapterInterface $adapter)
{
$finder = $this->buildFinder($adapter);
$finder->files()->in(self::$tmpDir);
// make 'foo' directory non-openable
chmod(self::$tmpDir.DIRECTORY_SEPARATOR.'foo', 0333);
try {
$this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->getIterator());
$this->fail('Finder should throw an exception when opening a non-readable directory.');
} catch (\Exception $e) {
$this->assertEquals('Symfony\\Component\\Finder\\Exception\\AccessDeniedException', get_class($e));
}
chmod(self::$tmpDir.DIRECTORY_SEPARATOR.'foo', 0777);
}
private function buildTestData(array $tests)
{
$data = array();