php-dataset/src/FilteringReaderIterator.php

97 lines
2.9 KiB
PHP

<?php
namespace NoccyLabs\Dataset;
use Iterator;
class FilteringReaderIterator implements Iterator
{
private Iterator $reader;
private $condition;
/**
*
* @note Removed support for callable in cond (php7.4 compat)
*/
public function __construct(Iterator $reader, array $condition)
{
$this->reader = $reader;
$this->condition = $condition;
}
public function current(): mixed
{
return $this->reader->current();
}
public function key(): mixed
{
return $this->reader->key();
}
public function valid(): bool
{
return $this->reader->valid();
}
public function next(): void
{
$this->reader->next();
while ($this->reader->valid()) {
$curr = $this->reader->current();
if ($this->matchCondition($curr))
break;
$this->reader->next();
}
}
public function rewind(): void
{
$this->reader->rewind();
while ($this->reader->valid()) {
$curr = $this->reader->current();
if ($this->matchCondition($curr))
break;
$this->reader->next();
}
}
/**
* Test a condition against a row
*
* The matched conditions are:
* - string/bool/int/float - match value
* - array - all conditions in array must match:
* - eq equals
* - neq not equals
* - gt greater than
* - gte greater than or equal
* - lt less than
* - in value in array
* - nin value not in array
*/
private function matchCondition(array $row): bool
{
if (is_callable($this->condition)) {
return (bool)call_user_func($this->condition, $row);
}
foreach ($this->condition as $field=>$test) {
if (!array_key_exists($field, $row)) continue;
if (is_array($test)) {
if (array_key_exists('eq',$test) && $row[$field] != $test['eq']) return false;
if (array_key_exists('neq',$test) && $row[$field] == $test['neq']) return false;
if (array_key_exists('gt',$test) && $row[$field] <= $test['gt']) return false;
if (array_key_exists('gte',$test) && $row[$field] < $test['gte']) return false;
if (array_key_exists('lt',$test) && $row[$field] >= $test['lt']) return false;
if (array_key_exists('lte',$test) && $row[$field] > $test['lte']) return false;
if (array_key_exists('in',$test) && !in_array($row[$field], $test['in'])) return false;
if (array_key_exists('nin',$test) && in_array($row[$field], $test['in'])) return false;
} else {
if ($row[$field] != $test) return false;
}
}
return true;
}
}