I have a class that is basically a decorator for PHP's DirectoryIterator. Each file's contents are processed by the class and then returned by the current()
method. Currently, when the file is a dot file or the file cannot be processed, I return false
from the current()
method. But I would rather like to skip the dot- and unprocessable files, and only return processed data.
P.S. The code below is a simplified example. I don't want to pre-process all files in the constructor.
class Pages implements \Iterator
{
public function __construct(string $path)
{
$this->di = new \DirectoryIterator($path);
}
public function rewind() {
return $this->di->rewind();
}
public function current() {
$file = $this->di->current();
if($file->isDot()) {
return false;
}
$content = file_get_contents($file->getPathName());
if($content === 'Cannot be processed!') {
return false;
}
return $content;
}
public function key() {
return $this->di->key();
}
public function next() {
return $this->di->next();
}
public function valid() {
return $this->di->valid();
}
}
You can greatly simplify the code of your own answer by extending the already existing abstract PHP class FilterIterator
:
class DirectoryFilterIterator
extends FilterIterator
{
public function __construct(string $path) {
parent::__construct(new DirectoryIterator($path));
}
public function accept() : bool {
$current = parent::current();
// let's not only ensure it's not a dot but that it's an actual readable file
if(!$current->isFile() || !$current->isReadable()) {
return false;
}
else {
$contents = file_get_contents($current->getPathname());
if($contents === 'Some value') {
return false;
}
}
return true;
}
}
foreach(new DirectoryFilterIterator('.') as $key => $value) {
echo "$key -> $value\n";
}
As you can also see, instead of merely ensuring that the item is not a dot, I ensure the item is an actual readable file as I think that is a little more robust for your intentions.
PS: As your original intention was to create a decorator/wrapper you can of course alter the constructor of DirectoryFilterIterator
to accept a DirectoryIterator
instead:
public function __construct(DirectoryIterator $it) {
parent::__construct($it);
}
...and then change the instantiation to:
foreach(new DirectoryFilterIterator(new DirectoryIterator('.')) as $key => $value) {
echo "$key -> $value\n";
}