1<?php 2 3namespace dokuwiki\plugin\struct\meta; 4 5/** 6 * This class builds a nested tree from a search result 7 * 8 * This is used to create the nested output in the AggregationList 9 */ 10class NestedResult 11{ 12 13 /** @var NestedValue[] */ 14 protected $nodes = []; 15 16 /** @var Value[][] */ 17 protected $result; 18 19 /** 20 * @param Value[][] $result the original search result 21 * @return void 22 */ 23 public function __construct($result) 24 { 25 $this->result = $result; 26 } 27 28 /** 29 * Get the nested result 30 * 31 * @param int $nesting the nesting level to use 32 * @return NestedValue the root node of the nested tree 33 */ 34 public function getRoot($nesting) { 35 $this->nodes = []; 36 $root = new NestedValue(null, -1); 37 38 if(!$this->result) return $root; 39 foreach ($this->result as $row) { 40 $this->nestBranch($root, $row, $nesting); 41 } 42 43 return $root; 44 } 45 46 /** 47 * Creates nested nodes for a given result row 48 * 49 * Splits up multi Values into separate nodes, when used in nesting 50 * 51 * @param Value[] $row current result row to work on 52 * @param int $nesting number of wanted nesting levels 53 * @param int $depth current nesting depth (used in recursion) 54 */ 55 protected function nestBranch(NestedValue $parent, $row, $nesting, $depth = 0) 56 { 57 // nesting level reached, add row and return 58 if($depth >= $nesting) { 59 $parent->addResultRow($row); 60 return; 61 } 62 63 $valObj = array_shift($row); 64 if (!$valObj) return; // no more values to nest, usually shouldn't happen 65 66 if ($valObj->getColumn()->isMulti()) { 67 // split up multi values into separate nodes 68 $values = $valObj->getValue(); 69 foreach ($values as $value) { 70 $newValue = new Value($valObj->getColumn(), $value); 71 $node = $this->getNodeForValue($newValue, $depth); 72 $parent->addChild($node); 73 $this->nestBranch($node, $row, $nesting, $depth + 1); 74 } 75 } else { 76 $node = $this->getNodeForValue($valObj, $depth); 77 $parent->addChild($node); 78 $this->nestBranch($node, $row, $nesting, $depth + 1); 79 80 } 81 } 82 83 /** 84 * Create or get existing Node from the tree 85 * 86 * @param Value $value 87 * @param int $depth 88 * @return NestedValue 89 */ 90 protected function getNodeForValue(Value $value, $depth) 91 { 92 $node = new NestedValue($value, $depth); 93 $key = (string) $node; 94 if (!isset($this->nodes[$key])) { 95 $this->nodes[$key] = $node; 96 } 97 return $this->nodes[$key]; 98 } 99} 100 101 102