Skip to content

Commit

Permalink
[Finder] refactored size and date comparators
Browse files Browse the repository at this point in the history
  • Loading branch information
fabpot committed May 21, 2010
1 parent efb5801 commit 9426f82
Show file tree
Hide file tree
Showing 12 changed files with 351 additions and 109 deletions.
64 changes: 64 additions & 0 deletions src/Symfony/Components/Finder/Comparator/Comparator.php
@@ -0,0 +1,64 @@
<?php

namespace Symfony\Components\Finder\Comparator;

/*
* 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.
*/

/**
* Comparator.
*
* @package Symfony
* @subpackage Components_Finder
* @author Fabien Potencier <fabien.potencier@symfony-project.com> PHP port
*/
class Comparator
{
protected $target;
protected $operator;

public function setTarget($target)
{
$this->target = $target;
}

public function setOperator($operator)
{
if (!$operator) {
$operator = '==';
}

if (!in_array($operator, array('>', '<', '>=', '<=', '=='))) {
throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator));
}

$this->operator = $operator;
}

/**
* Tests against the target.
*
* @param mixed $test A test value
*/
public function test($test)
{
switch ($this->operator) {
case '>':
return $test > $this->target;
case '>=':
return $test >= $this->target;
case '<':
return $test < $this->target;
case '<=':
return $test <= $this->target;
}

return $test == $this->target;
}
}
57 changes: 57 additions & 0 deletions src/Symfony/Components/Finder/Comparator/DateComparator.php
@@ -0,0 +1,57 @@
<?php

namespace Symfony\Components\Finder\Comparator;

/*
* 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.
*/

/**
* DateCompare compiles date comparisons.
*
* @package Symfony
* @subpackage Components_Finder
* @author Fabien Potencier <fabien.potencier@symfony-project.com> PHP port
*/
class DateComparator extends Comparator
{
protected $target;
protected $comparison;

/**
* Constructor.
*
* @param string $test A comparison string
*
* @throws \InvalidArgumentException If the test is not understood
*/
public function __construct($test)
{
if (!preg_match('#^\s*([<>=]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) {
throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a date test.', $test));
}

if (false === $target = @strtotime($matches[2])) {
throw new \InvalidArgumentException(sprintf('"%s" is not a valid date.', $matches[2]));
}

$operator = isset($matches[1]) ? $matches[1] : '==';
if ('since' === $operator || 'after' === $operator)
{
$operator = '>';
}

if ('until' === $operator || 'before' === $operator)
{
$operator = '<';
}

$this->setOperator($operator);
$this->setTarget($target);
}
}
@@ -1,6 +1,6 @@
<?php

namespace Symfony\Components\Finder;
namespace Symfony\Components\Finder\Comparator;

/*
* This file is part of the Symfony framework.
Expand Down Expand Up @@ -33,71 +33,45 @@
* @copyright 2002 Richard Clamp <richardc@unixbeard.net>
* @see http://physics.nist.gov/cuu/Units/binary.html
*/
class NumberCompare
class NumberComparator extends Comparator
{
protected $target;
protected $comparison;

/**
* Constructor.
*
* @param string $test A comparison string
*
* @throws \InvalidArgumentException If the test is not understood
*/
public function __construct($test)
{
if (!preg_match('#^\s*([<>=]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) {
throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a test.', $test));
throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test));
}

$this->target = $matches[2];
$this->comparison = isset($matches[1]) ? $matches[1] : '==';

$target = $matches[2];
$magnitude = strtolower(isset($matches[3]) ? $matches[3] : '');
switch ($magnitude) {
case 'k':
$this->target *= 1000;
$target *= 1000;
break;
case 'ki':
$this->target *= 1024;
$target *= 1024;
break;
case 'm':
$this->target *= 1000000;
$target *= 1000000;
break;
case 'mi':
$this->target *= 1024*1024;
$target *= 1024*1024;
break;
case 'g':
$this->target *= 1000000000;
$target *= 1000000000;
break;
case 'gi':
$this->target *= 1024*1024*1024;
$target *= 1024*1024*1024;
break;
}
}

/**
* Tests a number against the test.
*
* @throws \InvalidArgumentException If the test is not understood
*/
public function test($number)
{
if ($this->comparison === '>') {
return ($number > $this->target);
}

if ($this->comparison === '>=') {
return ($number >= $this->target);
}

if ($this->comparison === '<') {
return ($number < $this->target);
}

if ($this->comparison === '<=') {
return ($number <= $this->target);
}

return ($number == $this->target);
$this->setTarget($target);
$this->setOperator(isset($matches[1]) ? $matches[1] : '==');
}
}
51 changes: 15 additions & 36 deletions src/Symfony/Components/Finder/Finder.php
Expand Up @@ -43,8 +43,7 @@ class Finder implements \IteratorAggregate
protected $sort = false;
protected $ignoreVCS = true;
protected $dirs = array();
protected $minDate = false;
protected $maxDate = false;
protected $dates = array();

/**
* Restricts the matching to directories only.
Expand Down Expand Up @@ -107,46 +106,26 @@ public function minDepth($level)
}

/**
* Sets the maximum date (last modified) for a file or directory.
* Adds tests for file dates (last modified).
*
* The date must be something that strtotime() is able to parse:
*
* $finder->maxDate('yesterday');
* $finder->maxDate('2 days ago');
* $finder->maxDate('now - 2 hours');
* $finder->maxDate('2005-10-15');
* $finder->date('since yesterday');
* $finder->date('until 2 days ago');
* $finder->date('> now - 2 hours');
* $finder->date('>= 2005-10-15');
*
* @param string $date A date
* @param string $date A date rage string
*
* @return Symfony\Components\Finder The current Finder instance
*
* @see strtotime
* @see Symfony\Components\Finder\Iterator\DateRangeFilterIterator
* @see Symfony\Components\Finder\Comparator\DateComparator
*/
public function maxDate($date)
public function date($date)
{
if (false === $this->maxDate = @strtotime($date)) {
throw new \InvalidArgumentException(sprintf('"%s" is not a valid date'));
}

return $this;
}

/**
* Sets the minimum date (last modified) for a file or a directory.
*
* The date must be something that strtotime() is able to parse (@see maxDate()).
*
* @param string $date A date
*
* @return Symfony\Components\Finder The current Finder instance
*
* @see Symfony\Components\Finder\Iterator\DateRangeFilterIterator
*/
public function minDate($date)
{
if (false === $this->minDate = @strtotime($date)) {
throw new \InvalidArgumentException(sprintf('"%s" is not a valid date'));
}
$this->dates[] = new Comparator\DateComparator($date);

return $this;
}
Expand Down Expand Up @@ -201,11 +180,11 @@ public function notName($pattern)
* @return Symfony\Components\Finder The current Finder instance
*
* @see Symfony\Components\Finder\Iterator\SizeRangeFilterIterator
* @see Symfony\Components\Finder\NumberCompare
* @see Symfony\Components\Finder\Comparator\NumberComparator
*/
public function size($size)
{
$this->sizes[] = new NumberCompare($size);
$this->sizes[] = new Comparator\NumberComparator($size);

return $this;
}
Expand Down Expand Up @@ -410,8 +389,8 @@ protected function searchInDirectory($dir)
$iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes);
}

if (false !== $this->minDate || false !== $this->maxDate) {
$iterator = new Iterator\DateRangeFilterIterator($iterator, $this->minDate, $this->maxDate);
if ($this->dates) {
$iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates);
}

if ($this->filters) {
Expand Down
22 changes: 8 additions & 14 deletions src/Symfony/Components/Finder/Iterator/DateRangeFilterIterator.php
Expand Up @@ -20,20 +20,17 @@
*/
class DateRangeFilterIterator extends \FilterIterator
{
protected $minDate = false;
protected $maxDate = false;
protected $patterns = array();

/**
* Constructor.
*
* @param \Iterator $iterator The Iterator to filter
* @param integer $minDate The minimum date
* @param integer $maxDate The maximum date
* @param array $patterns An array of \DateCompare instances
*/
public function __construct(\Iterator $iterator, $minDate = false, $maxDate = false)
public function __construct(\Iterator $iterator, array $patterns)
{
$this->minDate = $minDate;
$this->maxDate = $maxDate;
$this->patterns = $patterns;

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

$filedate = $fileinfo->getMTime();

if (
(false !== $this->minDate && $filedate < $this->minDate)
||
(false !== $this->maxDate && $filedate > $this->maxDate)
) {
return false;
foreach ($this->patterns as $compare) {
if (!$compare->test($filedate)) {
return false;
}
}

return true;
Expand Down

0 comments on commit 9426f82

Please sign in to comment.