93 lines
2.8 KiB
PHP
93 lines
2.8 KiB
PHP
|
<?php
|
||
|
|
||
|
namespace NoccyLabs\Dataset;
|
||
|
|
||
|
use Iterator;
|
||
|
|
||
|
class FilteringReaderIterator implements Iterator
|
||
|
{
|
||
|
private Iterator $reader;
|
||
|
|
||
|
private $condition;
|
||
|
|
||
|
public function __construct(Iterator $reader, array|callable $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;
|
||
|
}
|
||
|
}
|