Skip to content

Instantly share code, notes, and snippets.

@kabel
Created April 20, 2012 22:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kabel/2432298 to your computer and use it in GitHub Desktop.
Save kabel/2432298 to your computer and use it in GitHub Desktop.
Compare PHP RecursiveIteratorIterator use with FilterIteractors
<?php
/*
Filesystem layout of ./backup/
total 0
drwxrwxr-x 3 kabel staff 102 Apr 20 16:00 db
drwxrwx--x 3 root wheel 102 Apr 20 16:31 do-not-backup
./db:
total 8
-rw-rw-r-- 1 kabel staff 1 Apr 20 16:00 foo
./do-not-backup:
total 0
-rw-r--r-- 1 kabel staff 0 Apr 20 16:31 bar
*/
/**
* @author kabel
*
* @method RecursiveDirectoryIterator getInnerIterator()
* @method SplFileInfo current()
*/
class RecursiveDirectoryFilterIterator extends RecursiveFilterIterator
{
protected $_filters;
public function __construct(RecursiveDirectoryIterator $iterator, array $filters = array())
{
parent::__construct($iterator);
$this->_filters = $filters;
}
public function accept()
{
$current = (string)$this->current();
$currentFilename = $this->current()->getFilename();
if ($currentFilename == '.' || $currentFilename == '..') {
return false;
}
foreach ($this->_filters as $filter) {
if (false !== strpos($current, $filter)) {
return false;
}
}
return true;
}
public function getChildren()
{
return new self($this->getInnerIterator()->getChildren(), $this->_filters);
}
}
/* BEGIN file from the magento core - lib/Mage/Backup/Filesystem/Iterator/Filter.php: */
/**
* Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@magentocommerce.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade Magento to newer
* versions in the future. If you wish to customize Magento for your
* needs please refer to http://www.magentocommerce.com for more information.
*
* @category Mage
* @package Mage_Backup
* @copyright Copyright (c) 2010 Magento Inc. (http://www.magentocommerce.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
/**
* Filter Iterator
*
* @category Mage
* @package Mage_Backup
* @author Magento Core Team <core@magentocommerce.com>
*/
class Mage_Backup_Filesystem_Iterator_Filter extends FilterIterator
{
/**
* Array that is used for filtering
*
* @var array
*/
protected $_filters;
/**
* Constructor
*
* @param Iterator $iterator
* @param array $filters list of files to skip
*/
public function __construct(Iterator $iterator, array $filters)
{
parent::__construct($iterator);
$this->_filters = $filters;
}
/**
* Check whether the current element of the iterator is acceptable
*
* @return bool
*/
public function accept()
{
$current = $this->current()->__toString();
$currentFilename = $this->current()->getFilename();
if ($currentFilename == '.' || $currentFilename == '..') {
return false;
}
foreach ($this->_filters as $filter) {
if (false !== strpos($current, $filter)) {
return false;
}
}
return true;
}
}
/* END */
// Inner Filter <- good
$itr = new RecursiveIteratorIterator(new RecursiveDirectoryFilterIterator(
new RecursiveDirectoryIterator(dirname(__FILE__) . '/backup'), array('do-not-backup')
), RecursiveIteratorIterator::CHILD_FIRST);
foreach ($itr as $filePath => $fileInfo) {
echo $filePath . PHP_EOL;
}
// Outer Filter <- bad
$itr = new Mage_Backup_Filesystem_Iterator_Filter(new RecursiveIteratorIterator(
new RecursiveDirectoryIterator(dirname(__FILE__) . '/backup'), RecursiveIteratorIterator::CHILD_FIRST
), array('do-not-backup'));
// This loop will throw an exception when it reaches the directory owned by root (permission denied)
// even though it is marked to be filtered out. FATAL ERROR :(
foreach ($itr as $filePath => $fileInfo) {
echo $filePath . PHP_EOL;
}
@kabel
Copy link
Author

kabel commented Apr 20, 2012

It is important to note that this test REQUIRES the filesystem layout described at the top (specifically note that the do-not-backup directory is owned by a different user AND is not readable by my user).

This will produce output similar to:

/Users/kabel/phptest/backup/db/foo
/Users/kabel/phptest/backup/db
/Users/kabel/phptest/backup/db/foo
/Users/kabel/phptest/backup/db
PHP Fatal error:  Uncaught exception 'UnexpectedValueException' with message 'RecursiveDirectoryIterator::__construct(/Users/kabel/phptest/backup/do-not-backup): failed to open dir: Permission denied' in /Users/kabel/phptest/RecursiveDirectoryIterator-test.php:154
Stack trace:
#0 [internal function]: RecursiveDirectoryIterator->__construct('/Users/kabel/ph...', 0)
#1 [internal function]: RecursiveDirectoryIterator->getChildren()
#2 /Users/kabel/phptest/RecursiveDirectoryIterator-test.php(154): FilterIterator->next()
#3 {main}
  thrown in /Users/kabel/phptest/RecursiveDirectoryIterator-test.php on line 154

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment