public static function mapreduce($data, $mapFn, $reduceFn)
{
$mapResult = [];
$reduceResult = [];
$mapEmit = function ($key, $value) use(&$mapResult) {
$mapResult[$key][] = $value;
};
$reduceEmit = function ($obj) use(&$reduceResult) {
$reduceResult[] = $obj;
};
foreach ($data as $item) {
$mapFn($item, $mapEmit);
}
foreach ($mapResult as $key => $value) {
$reduceFn($key, $mapResult[$key], $reduceEmit);
}
return $reduceResult;
}
private function groupBulkActions($changeInfoList) { $bulkChangeInfoClasses = $this->bulkChangeInfoClasses; $groupedChangeInfos = ArrayUtils::mapreduce($changeInfoList, function (TrackedChangeInfo $item, $mapEmit) { $key = "{$item->getEntityName()}/{$item->getAction()}"; $mapEmit($key, $item); }, function ($key, $items, $reduceEmit) use($bulkChangeInfoClasses) { /** @var TrackedChangeInfo[] $items */ if (count($items) > 1) { $entityName = $items[0]->getEntityName(); if (isset($bulkChangeInfoClasses[$entityName])) { $reduceEmit(new $bulkChangeInfoClasses[$entityName]($items)); } else { $reduceEmit($items); } } else { $reduceEmit($items[0]); } }); $changeInfos = array(); foreach ($groupedChangeInfos as $changeInfoGroup) { if (is_array($changeInfoGroup)) { foreach ($changeInfoGroup as $changeInfo) { $changeInfos[] = $changeInfo; } } else { $changeInfos[] = $changeInfoGroup; } } return $changeInfos; }