merged branch gajdaw/finder_current_fix (PR #4335)

Commits
-------

3eb67fc [2.1][Component][Finder] $this->current() fix

Discussion
----------

[2.1][Component][Finder] $this->current() fix

Bug fix: yes
Feature addition: no
Backwards compatibility break: no
Symfony2 tests pass: [![Build Status](https://secure.travis-ci.org/gajdaw/symfony.png?branch=master)](http://travis-ci.org/gajdaw/symfony)
Fixes the following tickets: -
Todo: -
License of the code: MIT

One method to resolve `->in("ftp://...")` problem is to create `RecursiveDirectoryFtpIterator`.
(Details: [issue 3585](https://github.com/symfony/symfony/issues/3585))

I think that all filters should access the information about current item calling `current()` or `getInnerIterator()`. Otherwise it will not work if we replace `RecursiveDirectoryIterator` with ftp iterator inside `Finder`.

I'm not sure if that should go to 2.0 or 2.1 branch.

---------------------------------------------------------------------------

by travisbot at 2012-05-19T09:20:19Z

This pull request [passes](http://travis-ci.org/symfony/symfony/builds/1373361) (merged 9f247921 into 58b92453).

---------------------------------------------------------------------------

by gajdaw at 2012-05-19T10:51:10Z

Probably it should go to master branch, because it improves commit done to master:

f2fea97460

---------------------------------------------------------------------------

by travisbot at 2012-05-19T11:26:14Z

This pull request [passes](http://travis-ci.org/symfony/symfony/builds/1373982) (merged f9d1db8c into 58b92453).

---------------------------------------------------------------------------

by travisbot at 2012-05-19T11:51:25Z

This pull request [fails](http://travis-ci.org/symfony/symfony/builds/1374031) (merged f1b4b4f7 into 58b92453).

---------------------------------------------------------------------------

by travisbot at 2012-05-19T12:48:17Z

This pull request [passes](http://travis-ci.org/symfony/symfony/builds/1374303) (merged b6d073da into 58b92453).

---------------------------------------------------------------------------

by travisbot at 2012-05-19T13:28:18Z

This pull request [passes](http://travis-ci.org/symfony/symfony/builds/1374568) (merged fd144c96 into 58b92453).

---------------------------------------------------------------------------

by travisbot at 2012-05-19T13:35:38Z

This pull request [passes](http://travis-ci.org/symfony/symfony/builds/1374609) (merged 89a8d851 into 58b92453).

---------------------------------------------------------------------------

by travisbot at 2012-05-21T04:31:46Z

This pull request [passes](http://travis-ci.org/symfony/symfony/builds/1385764) (merged 0d5b8322 into 58b92453).

---------------------------------------------------------------------------

by travisbot at 2012-05-21T07:21:56Z

This pull request [passes](http://travis-ci.org/symfony/symfony/builds/1386545) (merged 3eb67fca into 1407f112).

---------------------------------------------------------------------------

by stof at 2012-06-09T13:24:14Z

seems good
This commit is contained in:
Fabien Potencier 2012-06-19 17:16:22 +02:00
commit 092b5dde62
8 changed files with 163 additions and 37 deletions

View File

@ -43,7 +43,7 @@ class ExcludeDirectoryFilterIterator extends \FilterIterator
*/
public function accept()
{
$path = $this->isDir() ? $this->getSubPathname() : $this->getSubPath();
$path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath();
$path = strtr($path, '\\', '/');
foreach ($this->patterns as $pattern) {
if (preg_match($pattern, $path)) {

View File

@ -43,9 +43,10 @@ class FileTypeFilterIterator extends \FilterIterator
*/
public function accept()
{
if (self::ONLY_DIRECTORIES === (self::ONLY_DIRECTORIES & $this->mode) && $this->isFile()) {
$fileinfo = $this->current();
if (self::ONLY_DIRECTORIES === (self::ONLY_DIRECTORIES & $this->mode) && $fileinfo->isFile()) {
return false;
} elseif (self::ONLY_FILES === (self::ONLY_FILES & $this->mode) && $this->isDir()) {
} elseif (self::ONLY_FILES === (self::ONLY_FILES & $this->mode) && $fileinfo->isDir()) {
return false;
}

View File

@ -30,13 +30,15 @@ class FilecontentFilterIterator extends MultiplePcreFilterIterator
return true;
}
if ($this->isDir() || !$this->isReadable()) {
$fileinfo = $this->current();
if ($fileinfo->isDir() || !$fileinfo->isReadable()) {
return false;
}
$content = @file_get_contents($filename = $this->getRealpath());
if (false === $content) {
throw new \RuntimeException(sprintf('Error reading file "%s".', $this->getRealpath()));
$content = $fileinfo->getContents();
if (!$content) {
return false;
}
// should at least not match one rule to exclude

View File

@ -28,7 +28,7 @@ class FilenameFilterIterator extends MultiplePcreFilterIterator
*/
public function accept()
{
$filename = $this->getFilename();
$filename = $this->current()->getFilename();
// should at least not match one rule to exclude
foreach ($this->noMatchRegexps as $regex) {

View File

@ -40,11 +40,12 @@ class SizeRangeFilterIterator extends \FilterIterator
*/
public function accept()
{
if (!$this->isFile()) {
$fileinfo = $this->current();
if (!$fileinfo->isFile()) {
return true;
}
$filesize = $this->getSize();
$filesize = $fileinfo->getSize();
foreach ($this->comparators as $compare) {
if (!$compare->test($filesize)) {
return false;

View File

@ -54,4 +54,22 @@ class SplFileInfo extends \SplFileInfo
{
return $this->relativePathname;
}
/**
* Returns the contents of the file
*
* @return string the contents of the file
*/
public function getContents()
{
$level = error_reporting(0);
$content = file_get_contents($this->getRealpath());
error_reporting($level);
if (false === $content) {
$error = error_get_last();
throw new \RuntimeException($error['message']);
}
return $content;
}
}

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\Finder\Tests\Iterator;
use Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator;
use Symfony\Component\Finder\Iterator\RecursiveDirectoryIterator;
class ExcludeDirectoryFilterIteratorTest extends RealIteratorTestCase
{
@ -20,7 +21,7 @@ class ExcludeDirectoryFilterIteratorTest extends RealIteratorTestCase
*/
public function testAccept($directories, $expected)
{
$inner = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator(sys_get_temp_dir().'/symfony2_finder', \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST);
$inner = new \RecursiveIteratorIterator(new RecursiveDirectoryIterator(sys_get_temp_dir().'/symfony2_finder', \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST);
$iterator = new ExcludeDirectoryFilterIterator($inner, $directories);

View File

@ -18,73 +18,176 @@ class FilecontentFilterIteratorTest extends IteratorTestCase
public function testAccept()
{
$inner = new ContentInnerNameIterator(array('test.txt'));
$inner = new MockFileListIterator(array('test.txt'));
$iterator = new FilecontentFilterIterator($inner, array(), array());
$this->assertIterator(array('test.txt'), $iterator);
}
public function testDirectory()
{
$inner = new ContentInnerNameIterator(array('directory'));
$inner = new MockFileListIterator(array('directory'));
$iterator = new FilecontentFilterIterator($inner, array('directory'), array());
$this->assertIterator(array(), $iterator);
}
public function testUnreadableFile()
{
$inner = new ContentInnerNameIterator(array('file r-'));
$inner = new MockFileListIterator(array('file r-'));
$iterator = new FilecontentFilterIterator($inner, array('file r-'), array());
$this->assertIterator(array(), $iterator);
}
/**
* @expectedException RuntimeException
* @dataProvider getTestFilterData
*/
public function testFileGetContents()
public function testFilter(\Iterator $inner, array $matchPatterns, array $noMatchPatterns, array $resultArray)
{
$inner = new ContentInnerNameIterator(array('file r+'));
$iterator = new FilecontentFilterIterator($inner, array('file r+'), array());
$array = iterator_to_array($iterator);
$iterator = new FilecontentFilterIterator($inner, $matchPatterns, $noMatchPatterns);
$this->assertIterator($resultArray, $iterator);
}
public function getTestFilterData()
{
$inner = new MockFileListIterator();
$inner[] = new MockSplFileInfo(array(
'name' => 'a.txt',
'contents' => 'Lorem ipsum...',
'type' => 'file',
'mode' => 'r+')
);
$inner[] = new MockSplFileInfo(array(
'name' => 'b.yml',
'contents' => 'dolor sit...',
'type' => 'file',
'mode' => 'r+')
);
$inner[] = new MockSplFileInfo(array(
'name' => 'some/other/dir/third.php',
'contents' => 'amet...',
'type' => 'file',
'mode' => 'r+')
);
$inner[] = new MockSplFileInfo(array(
'name' => 'unreadable-file.txt',
'contents' => false,
'type' => 'file',
'mode' => 'r+')
);
return array(
array($inner, array('.'), array(), array('a.txt', 'b.yml', 'some/other/dir/third.php')),
array($inner, array('ipsum'), array(), array('a.txt')),
array($inner, array('i', 'amet'), array('Lorem', 'amet'), array('b.yml')),
);
}
}
class ContentInnerNameIterator extends \ArrayIterator
class MockSplFileInfo extends \SplFileInfo
{
public function current()
{
return new \SplFileInfo(parent::current());
}
const TYPE_DIRECTORY = 1;
const TYPE_FILE = 2;
const TYPE_UNKNOWN = 3;
public function getFilename()
private $contents = null;
private $mode = null;
private $type = null;
public function __construct($param)
{
return parent::current();
if (is_string($param)) {
parent::__construct($param);
} elseif (is_array($param)) {
$defaults = array(
'name' => 'file.txt',
'contents' => null,
'mode' => null,
'type' => null
);
$defaults = array_merge($defaults, $param);
parent::__construct($defaults['name']);
$this->setContents($defaults['contents']);
$this->setMode($defaults['mode']);
$this->setType($defaults['type']);
} else {
throw new \RuntimeException(sprintf('Incorrect parameter "%s"', $param));
}
}
public function isFile()
{
$name = parent::current();
if ($this->type === null) {
return preg_match('/file/', $this->getFilename());
};
return preg_match('/file/', $name);
return self::TYPE_FILE === $this->type;
}
public function isDir()
{
$name = parent::current();
if ($this->type === null) {
return preg_match('/directory/', $this->getFilename());
}
return preg_match('/directory/', $name);
}
public function getRealpath()
{
return parent::current();
return self::TYPE_DIRECTORY === $this->type;
}
public function isReadable()
{
$name = parent::current();
if ($this->mode === null) {
return preg_match('/r\+/', $this->getFilename());
}
return preg_match('/r\+/', $name);
return preg_match('/r\+/', $this->mode);
}
public function getContents()
{
return $this->contents;
}
public function setContents($contents)
{
$this->contents = $contents;
}
public function setMode($mode)
{
$this->mode = $mode;
}
public function setType($type)
{
if (is_string($type)) {
switch ($type) {
case 'directory':
$this->type = self::TYPE_DIRECTORY;
case 'd':
$this->type = self::TYPE_DIRECTORY;
break;
case 'file':
$this->type = self::TYPE_FILE;
case 'f':
$this->type = self::TYPE_FILE;
break;
default:
$this->type = self::TYPE_UNKNOWN;
}
} else {
$this->type = $type;
}
}
}
class MockFileListIterator extends \ArrayIterator
{
public function __construct(array $filesArray = array())
{
$files = array_map(function($file){ return new MockSplFileInfo($file); }, $filesArray);
parent::__construct($files);
}
}