1<?php 2// (c) Copyright by authors of the Tiki Wiki CMS Groupware Project 3// 4// All Rights Reserved. See copyright.txt for details and a complete list of authors. 5// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details. 6// $Id$ 7 8class Math_Formula_Function_Subtotal extends Math_Formula_Function 9{ 10 function evaluate($element) 11 { 12 $allowed = ['list', 'group', 'aggregate', 'separators', 'formula']; 13 14 if ($extra = $element->getExtraValues($allowed)) { 15 $this->error(tr('Unexpected values: %0', implode(', ', $extra))); 16 } 17 18 $list = $element->list; 19 if (! $list || count($list) != 1) { 20 $this->error(tra('Field must be provided and contain one argument: list')); 21 } 22 $list = $this->evaluateChild($list[0]); 23 24 $group = $element->group; 25 if (! $group || count($group) != 1) { 26 $this->error(tra('Field must be provided and contain one argument: group.')); 27 } 28 $group = $group[0]; 29 30 $aggregate = $element->aggregate; 31 if (! $aggregate || count($aggregate) < 1) { 32 $this->error(tra('Field must be provided and contain at least one argument: aggregate.')); 33 } 34 35 $separators = $element->separators; 36 if (! $separators || count($separators) != 2) { 37 $separators = ["|", "\n"]; 38 } else { 39 $separators = [$this->evaluateChild($separators[0]), $this->evaluateChild($separators[1])]; 40 } 41 42 $formula = $element->formula; 43 if (! $formula) { 44 $formula = []; 45 } 46 47 $out = []; 48 49 // group values by field 50 if (is_array($list)) { 51 foreach ($list as $values) { 52 if (! isset($values[$group])) { 53 continue; 54 } 55 $group_value = trim($values[$group]); 56 if (! isset($out[$group_value])) { 57 $out[$group_value] = ['group' => $group_value]; 58 foreach ($aggregate as $position => $field) { 59 $out[$group_value][$position] = []; 60 } 61 } 62 foreach ($aggregate as $position => $field) { 63 if (is_string($field) && !isset($values[$field])) { 64 $value = 0; 65 } else { 66 $value = $this->evaluateChild($field, $values); 67 } 68 $out[$group_value][$position][] = $value; 69 } 70 } 71 } 72 73 // evaluate aggregate function for each field 74 foreach ($out as $group_value => $rows) { 75 foreach ($aggregate as $position => $field) { 76 $function = str_replace(' ', '', ucwords(str_replace('-', ' ', $formula[$position] ?? 'add'))); 77 $class = 'Math_Formula_Function_'.$function; 78 if (class_exists($class)) { 79 $op = new $class; 80 $out[$group_value][$position] = $op->evaluateTemplate($rows[$position], function($child) { return $child; }); 81 } 82 } 83 } 84 85 return implode($separators[1], array_map(function($row) use ($separators) { 86 return implode($separators[0], $row); 87 }, $out)); 88 } 89} 90