merged branch vicb/finder/regex (PR #4028)

Commits
-------

f728463 [Finder] Fixes in the iterators

Discussion
----------

[Finder] Fixes in the iterators

fix: #4023
ref: #4011

- Fix regex detection
- call `file_get_contents()` only once (vs once per pattern)

[![Build Status](https://secure.travis-ci.org/vicb/symfony.png?branch=finder/regex)](http://travis-ci.org/vicb/symfony)

@gajdaw thoughts ?
This commit is contained in:
Fabien Potencier 2012-04-20 14:18:46 +02:00
commit 736886688f
4 changed files with 127 additions and 58 deletions

View File

@ -26,41 +26,34 @@ class FilecontentFilterIterator extends MultiplePcreFilterIterator
*/
public function accept()
{
// should at least match one rule
if ($this->matchRegexps) {
$match = false;
foreach ($this->matchRegexps as $regex) {
$content = file_get_contents($this->getRealpath());
if (false === $content) {
throw new \RuntimeException(sprintf('Error reading file "%s".', $this->getRealpath()));
}
if (preg_match($regex, $content)) {
$match = true;
break;
}
}
} else {
$match = true;
if (!$this->matchRegexps && !$this->noMatchRegexps) {
return true;
}
$content = file_get_contents($this->getRealpath());
if (false === $content) {
throw new \RuntimeException(sprintf('Error reading file "%s".', $this->getRealpath()));
}
// should at least not match one rule to exclude
if ($this->noMatchRegexps) {
$exclude = false;
foreach ($this->noMatchRegexps as $regex) {
$content = file_get_contents($this->getRealpath());
if (false === $content) {
throw new \RuntimeException(sprintf('Error reading file "%s".', $this->getRealpath()));
}
if (preg_match($regex, $content)) {
$exclude = true;
break;
}
foreach ($this->noMatchRegexps as $regex) {
if (preg_match($regex, $content)) {
return false;
}
} else {
$exclude = false;
}
return $match && !$exclude;
// should at least match one rule
$match = true;
if ($this->matchRegexps) {
$match = false;
foreach ($this->matchRegexps as $regex) {
if (preg_match($regex, $content)) {
return true;
}
}
}
return $match;
}
/**
@ -72,10 +65,6 @@ class FilecontentFilterIterator extends MultiplePcreFilterIterator
*/
protected function toRegex($str)
{
if (preg_match('/^([^a-zA-Z0-9\\\\]).+?\\1[ims]?$/', $str)) {
return $str;
}
return sprintf('/%s/', preg_quote($str, '/'));
return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
}
}

View File

@ -28,33 +28,27 @@ class FilenameFilterIterator extends MultiplePcreFilterIterator
*/
public function accept()
{
$filename = $this->getFilename();
// should at least not match one rule to exclude
foreach ($this->noMatchRegexps as $regex) {
if (preg_match($regex, $filename)) {
return false;
}
}
// should at least match one rule
$match = true;
if ($this->matchRegexps) {
$match = false;
foreach ($this->matchRegexps as $regex) {
if (preg_match($regex, $this->getFilename())) {
$match = true;
break;
if (preg_match($regex, $filename)) {
return true;
}
}
} else {
$match = true;
}
// should at least not match one rule to exclude
if ($this->noMatchRegexps) {
$exclude = false;
foreach ($this->noMatchRegexps as $regex) {
if (preg_match($regex, $this->getFilename())) {
$exclude = true;
break;
}
}
} else {
$exclude = false;
}
return $match && !$exclude;
return $match;
}
/**
@ -69,10 +63,6 @@ class FilenameFilterIterator extends MultiplePcreFilterIterator
*/
protected function toRegex($str)
{
if (preg_match('/^([^a-zA-Z0-9\\\\]).+?\\1[ims]?$/', $str)) {
return $str;
}
return Glob::toRegex($str);
return $this->isRegex($str) ? $str : Glob::toRegex($str);
}
}

View File

@ -44,6 +44,31 @@ abstract class MultiplePcreFilterIterator extends \FilterIterator
parent::__construct($iterator);
}
/**
* Checks whether the string is a regex.
*
* @param string $str
*
* @return Boolean Whether the given string is a regex
*/
protected function isRegex($str) {
if (preg_match('/^(.{3,}?)[imsxuADU]*$/', $str, $m)) {
$start = substr($m[1], 0, 1);
$end = substr($m[1], -1);
if ($start === $end) {
return !preg_match('/[[:alnum:] \\\\]/', $start);
}
if ($start === '{' && $end === '}') {
return true;
}
}
return false;
}
/**
* Converts string into regexp.
*

View File

@ -0,0 +1,65 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Finder\Tests\Iterator;
use Symfony\Component\Finder\Iterator\MultiplePcreFilterIterator;
class MultiplePcreFilterIteratorTest extends \PHPUnit_Framework_TestCase
{
/**
* @dataProvider getIsRegexFixtures
*/
public function testIsRegex($string, $isRegex, $message)
{
$testIterator = new TestMultiplePcreFilterIterator();
$this->assertEquals($isRegex, $testIterator->isRegex($string), $message);
}
public function getIsRegexFixtures()
{
return array(
array('foo', false, 'string'),
array(' foo ', false, '" " is not a valid delimiter'),
array('\\foo\\', false, '"\\" is not a valid delimiter'),
array('afooa', false, '"a" is not a valid delimiter'),
array('//', false, 'the pattern should contain at least 1 character'),
array('/a/', true, 'valid regex'),
array('/foo/', true, 'valid regex'),
array('/foo/i', true, 'valid regex with a single modifier'),
array('/foo/imsxu', true, 'valid regex with multiple modifiers'),
array('#foo#', true, '"#" is a valid delimiter'),
array('{foo}', true, '"{,}" is a valid delimiter pair'),
);
}
}
class TestMultiplePcreFilterIterator extends MultiplePcreFilterIterator
{
public function __construct()
{
}
public function accept()
{
throw new \BadFunctionCallException('Not implemented');
}
public function isRegex($str)
{
return parent::isRegex($str);
}
public function toRegex($str)
{
throw new \BadFunctionCallException('Not implemented');
}
}