/** * Processes one line of data passed on to it and digs lowers with it * First, it saves the current data to this group * Second it processes all aggregators * Third it extract the next grouper in line, processes it to get the group from this grouper * Fourth checks if the group for that grouper already exists, if not creates one, stores it * Finaly, sends the same arguments to the sub group with one less grouper * * Creates a recursive tree of groups where the data references are aggregated and stored for looping * * @param mixed $data Data to process in the different groupers and aggregators, this is only one line * @param mixed $key Key to process in the different groupers and aggregators, this is only one line * @param mixed \array Array of groupers, only the first one is used, the rest are passed down the current group for further processing * @param mixed \array Array of aggregators, all processed and values are stored inside the current group result * * @access public */ public function process($data, $key, array $groupers, array $aggregators) { //Add the data to the current group //Keep a reference, do not copy the data $this->data[] = $data; //Process the aggregators foreach ($aggregators as $aggregator) { //If the object is not an aggregator if (!is_object($aggregator) || !$aggregator instanceof AggregatorInterface) { throw new InvalidArgumentException('Aggregator value resolved from $aggregators array is not an AggregatorInterface object, aborting data processing'); } //Process the aggregation $aggregator->aggregate($this, $data, $key); } //If there are groupers in the groupers array if (count($groupers) > 0) { //Get the next grouper $grouper = array_shift($groupers); if (!is_object($grouper) || !$grouper instanceof GrouperInterface) { throw new InvalidArgumentException('Grouper shifted out of $groupers array is not a GrouperInterface object, aborting data processing'); } $groupValue = $grouper->getGroupedOnValue($data, $key); //Check if that groupValue already exists if ($this->hasGroup($groupValue) == false) { $newGroup = new self(); $newGroup->setGroupValue($groupValue); $this->addGroup($newGroup, $groupValue); } $group = $this->getGroup($groupValue); //Process this group with remaining groupers $group->process($data, $key, $groupers, $aggregators); } }