Skip to content

Commit

Permalink
[Finder] refactored directory depth management
Browse files Browse the repository at this point in the history
  • Loading branch information
fabpot committed May 21, 2010
1 parent 9426f82 commit 360f79f
Show file tree
Hide file tree
Showing 10 changed files with 194 additions and 108 deletions.
32 changes: 31 additions & 1 deletion src/Symfony/Components/Finder/Comparator/Comparator.php
Expand Up @@ -21,13 +21,43 @@
class Comparator
{
protected $target;
protected $operator;
protected $operator = '==';

/**
* Gets the target value.
*
* @return string The target value
*/
public function getTarget()
{
return $this->target;
}

/**
* Sets the target value.
*
* @param string $target The target value
*/
public function setTarget($target)
{
$this->target = $target;
}

/**
* Gets the comparison operator.
*
* @return string The operator
*/
public function getOperator()
{
return $this->operator;
}

/**
* Sets the comparison operator.
*
* @param string $operator A valid operator
*/
public function setOperator($operator)
{
if (!$operator) {
Expand Down
Expand Up @@ -12,7 +12,7 @@
*/

/**
* NumberCompare compiles a simple comparison to an anonymous
* NumberComparator compiles a simple comparison to an anonymous
* subroutine, which you can call with a value to be tested again.
*
* Now this would be very pointless, if NumberCompare didn't understand
Expand Down
45 changes: 14 additions & 31 deletions src/Symfony/Components/Finder/Finder.php
Expand Up @@ -16,14 +16,12 @@
*
* It is a thin wrapper around several specialized iterator classes.
*
* All rules may be invoked several times, except for ->in() method.
* Some rules are cumulative (->name() for example) whereas others are destructive
* (most recent value is used, ->maxDepth() method for example).
* All rules may be invoked several times.
*
* All methods return the current Finder object to allow easy chaining:
*
* $finder = new Finder();
* $iterator = $finder->files()->name('*.php')->in(__DIR__);
* $finder = $finder->files()->name('*.php')->in(__DIR__);
*
* @package Symfony
* @subpackage Components_Finder
Expand All @@ -36,8 +34,7 @@ class Finder implements \IteratorAggregate
protected $notNames = array();
protected $exclude = array();
protected $filters = array();
protected $minDepth = 0;
protected $maxDepth = INF;
protected $depths = array();
protected $sizes = array();
protected $followLinks = false;
protected $sort = false;
Expand Down Expand Up @@ -70,37 +67,23 @@ public function files()
}

/**
* Sets the maximum directory depth.
* Adds tests for the directory depth.
*
* The Finder will descend at most $level levels of directories below the starting point.
* Usage:
*
* @param int $level The max depth
* $finder->depth('> 1') // the Finder will start matching at level 1.
* $finder->depth('< 3') // the Finder will descend at most 3 levels of directories below the starting point.
*
* @return Symfony\Components\Finder The current Finder instance
*
* @see Symfony\Components\Finder\Iterator\LimitDepthFilterIterator
*/
public function maxDepth($level)
{
$this->maxDepth = (double) $level;

return $this;
}

/**
* Sets the minimum directory depth.
*
* The Finder will start matching at level $level.
*
* @param int $level The min depth
* @param int $level The depth level expression
*
* @return Symfony\Components\Finder The current Finder instance
*
* @see Symfony\Components\Finder\Iterator\LimitDepthFilterIterator
* @see Symfony\Components\Finder\Iterator\DepthRangeFilterIterator
* @see Symfony\Components\Finder\Comparator\NumberComparator
*/
public function minDepth($level)
public function depth($level)
{
$this->minDepth = (integer) $level;
$this->depths[] = new Comparator\NumberComparator($level);

return $this;
}
Expand Down Expand Up @@ -365,8 +348,8 @@ protected function searchInDirectory($dir)

$iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir, $flags), \RecursiveIteratorIterator::SELF_FIRST);

if ($this->minDepth > 0 || $this->maxDepth < INF) {
$iterator = new Iterator\LimitDepthFilterIterator($iterator, $this->minDepth, $this->maxDepth);
if ($this->depths) {
$iterator = new Iterator\DepthRangeFilterIterator($iterator, $this->depths);
}

if ($this->mode) {
Expand Down
Expand Up @@ -20,17 +20,17 @@
*/
class DateRangeFilterIterator extends \FilterIterator
{
protected $patterns = array();
protected $comparators = array();

/**
* Constructor.
*
* @param \Iterator $iterator The Iterator to filter
* @param array $patterns An array of \DateCompare instances
* @param \Iterator $iterator The Iterator to filter
* @param array $comparators An array of \DateCompare instances
*/
public function __construct(\Iterator $iterator, array $patterns)
public function __construct(\Iterator $iterator, array $comparators)
{
$this->patterns = $patterns;
$this->comparators = $comparators;

parent::__construct($iterator);
}
Expand All @@ -49,7 +49,7 @@ public function accept()
}

$filedate = $fileinfo->getMTime();
foreach ($this->patterns as $compare) {
foreach ($this->comparators as $compare) {
if (!$compare->test($filedate)) {
return false;
}
Expand Down
@@ -0,0 +1,69 @@
<?php

namespace Symfony\Components\Finder\Iterator;

/*
* This file is part of the Symfony framework.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

/**
* DepthRangeFilterIterator limits the directory depth.
*
* @package Symfony
* @subpackage Components_Finder
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class DepthRangeFilterIterator extends \FilterIterator
{
protected $minDepth = 0;

/**
* Constructor.
*
* @param \Iterator $iterator The Iterator to filter
* @param array $comparators An array of \NumberComparator instances
*/
public function __construct(\RecursiveIteratorIterator $iterator, array $comparators)
{
$minDepth = 0;
$maxDepth = INF;
foreach ($comparators as $comparator) {
switch ($comparator->getOperator()) {
case '>':
$minDepth = $comparator->getTarget() + 1;
break;
case '>=':
$minDepth = $comparator->getTarget();
break;
case '<':
$maxDepth = $comparator->getTarget() - 1;
break;
case '<=':
$maxDepth = $comparator->getTarget();
break;
default:
$minDepth = $maxDepth = $comparator->getTarget();
}
}

$this->minDepth = $minDepth;
$iterator->setMaxDepth(INF === $maxDepth ? -1 : $maxDepth);

parent::__construct($iterator);
}

/**
* Filters the iterator values.
*
* @return Boolean true if the value should be kept, false otherwise
*/
public function accept()
{
return $this->getInnerIterator()->getDepth() >= $this->minDepth;
}
}

This file was deleted.

Expand Up @@ -20,17 +20,17 @@
*/
class SizeRangeFilterIterator extends \FilterIterator
{
protected $patterns = array();
protected $comparators = array();

/**
* Constructor.
*
* @param \Iterator $iterator The Iterator to filter
* @param array $patterns An array of \NumberCompare instances
* @param \Iterator $iterator The Iterator to filter
* @param array $comparators An array of \NumberComparator instances
*/
public function __construct(\Iterator $iterator, array $patterns)
public function __construct(\Iterator $iterator, array $comparators)
{
$this->patterns = $patterns;
$this->comparators = $comparators;

parent::__construct($iterator);
}
Expand All @@ -49,7 +49,7 @@ public function accept()
}

$filesize = $fileinfo->getSize();
foreach ($this->patterns as $compare) {
foreach ($this->comparators as $compare) {
if (!$compare->test($filesize)) {
return false;
}
Expand Down
Expand Up @@ -15,7 +15,7 @@

class ComparatorTest extends \PHPUnit_Framework_TestCase
{
public function testSetOperator()
public function testGetSetOperator()
{
$comparator = new Comparator();
try {
Expand All @@ -24,6 +24,17 @@ public function testSetOperator()
} catch (\Exception $e) {
$this->assertInstanceOf('InvalidArgumentException', $e, '->setOperator() throws an \InvalidArgumentException if the operator is not valid.');
}

$comparator = new Comparator();
$comparator->setOperator('>');
$this->assertEquals('>', $comparator->getOperator(), '->getOperator() returns the current operator');
}

public function testGetSetTarget()
{
$comparator = new Comparator();
$comparator->setTarget(8);
$this->assertEquals(8, $comparator->getTarget(), '->getTarget() returns the target');
}

/**
Expand Down
21 changes: 9 additions & 12 deletions tests/Symfony/Tests/Components/Finder/FinderTest.php
Expand Up @@ -52,25 +52,22 @@ public function testFiles()
$this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator());
}

public function testMaxDepth()
public function testDepth()
{
$finder = new Finder();
$this->assertSame($finder, $finder->maxDepth(0));
$this->assertSame($finder, $finder->depth('< 1'));
$this->assertIterator($this->toAbsolute(array('foo', 'test.php', 'test.py', 'toto')), $finder->in(self::$tmpDir)->getIterator());
}

public function testMinDepth()
{
$finder = new Finder();
$this->assertSame($finder, $finder->minDepth(1));
$this->assertSame($finder, $finder->depth('<= 0'));
$this->assertIterator($this->toAbsolute(array('foo', 'test.php', 'test.py', 'toto')), $finder->in(self::$tmpDir)->getIterator());

$finder = new Finder();
$this->assertSame($finder, $finder->depth('>= 1'));
$this->assertIterator($this->toAbsolute(array('foo/bar.tmp')), $finder->in(self::$tmpDir)->getIterator());
}

public function testMinMaxDepth()
{
$finder = new Finder();
$finder->maxDepth(0);
$finder->minDepth(1);
$finder->depth('< 1')->depth('>= 1');
$this->assertIterator(array(), $finder->in(self::$tmpDir)->getIterator());
}

Expand Down Expand Up @@ -187,7 +184,7 @@ public function testIn()
}

$finder = new Finder();
$iterator = $finder->files()->name('*.php')->maxDepth(0)->in(array(self::$tmpDir, __DIR__))->getIterator();
$iterator = $finder->files()->name('*.php')->depth('< 1')->in(array(self::$tmpDir, __DIR__))->getIterator();

$this->assertIterator(array(self::$tmpDir.'test.php', __DIR__.'/FinderTest.php', __DIR__.'/GlobTest.php'), $iterator);
}
Expand Down

0 comments on commit 360f79f

Please sign in to comment.