callableForId = $callableForId; return $this; } /** * @param callable $callableForData * @return $this */ public function callableDataIs(callable $callableForData) { $this->callableForData = $callableForData; return $this; } /** * @param callable $callableFinalizeAggregate * @return $this */ public function callableFinalizeAggregate(callable $callableFinalizeAggregate) { $this->callableFinalizeAggregate = $callableFinalizeAggregate; return $this; } /** * @return \Generator */ public function getIterator() { $knownIdentifiers = []; $callableForId = $this->callableForId; $callableForData = $this->callableForData; $previousId = null; $previousResult = null; $previousKey = null; $currentId = null; $aggregate = []; $key = null; $result = null; foreach ($this->result as $key => $columns) { $result = $this->hydrateColumns( $this->result->getConnectionName(), $this->result->getDatabase(), $columns ); $currentId = $callableForId($result); if (isset($knownIdentifiers[$currentId]) === true) { continue; } if ($previousId === null) { $previousId = $currentId; $previousResult = $result; $previousKey = $key; } if ($previousId === $currentId) { $aggregate[] = $callableForData($result); } else { $previousResult = $this->finalizeAggregate($previousResult, $aggregate); $knownIdentifiers[$previousId] = true; yield $previousKey => $previousResult; $aggregate = [$callableForData($result)]; $previousId = $currentId; $previousResult = $result; $previousKey = $key; } } if ($previousId === $currentId && $previousId !== null) { yield $key => $this->finalizeAggregate($result, $aggregate); } } /** * @param mixed $result * @param mixed $aggregate * * @return mixed */ private function finalizeAggregate($result, $aggregate) { if ($this->callableFinalizeAggregate === null) { $result['aggregate'] = $aggregate; return $result; } $callableFinalizeAggregate = $this->callableFinalizeAggregate; return $callableFinalizeAggregate($result, $aggregate); } }