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