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:
commit
e5be0ded50
@ -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);
|
||||
|
||||
|
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Finder\Exception;
|
||||
|
||||
/**
|
||||
* @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
|
||||
*/
|
||||
class AccessDeniedException extends \UnexpectedValueException
|
||||
{
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
Reference in New Issue
Block a user