1<?php 2 3namespace dokuwiki\plugin\struct\meta; 4 5use dokuwiki\Utf8\Sort; 6 7/** 8 * Object to create a tree of values 9 * 10 * You should not create these yourself, but use the NestedResult class instead 11 */ 12class NestedValue 13{ 14 15 /** @var Value */ 16 protected $value; 17 18 /** @var NestedValue[] */ 19 protected $children = []; 20 21 /** @var Value[][] */ 22 protected $resultRows = []; 23 24 /** @var int the nesting depth */ 25 protected $depth; 26 27 /** 28 * Create a nested version of the given value 29 * 30 * @param Value|null $value The value to store, null for root node 31 * @param int $depth The depth of this node (avoids collision where the same values are selected on multiple levels) 32 */ 33 public function __construct(?Value $value, $depth = 0) 34 { 35 $this->value = $value; 36 $this->depth = $depth; 37 } 38 39 /** 40 * @return int 41 */ 42 public function getDepth() 43 { 44 return $this->depth; 45 } 46 47 /** 48 * Access the stored value 49 * 50 * @return Value|null the value stored in this node, null for root node 51 */ 52 public function getValueObject() 53 { 54 return $this->value; 55 } 56 57 /** 58 * Add a child node 59 * 60 * Nodes with the same key (__toString()) will be overwritten 61 * 62 * @param NestedValue $child 63 * @return void 64 */ 65 public function addChild(NestedValue $child) 66 { 67 $this->children[(string)$child] = $child; // ensures uniqueness 68 } 69 70 /** 71 * Get all child nodes 72 * 73 * @return NestedValue[] 74 */ 75 public function getChildren() 76 { 77 $children = $this->children; 78 usort($children, [$this, 'sortChildren']); 79 return $children; 80 } 81 82 /** 83 * Add a result row to this node 84 * 85 * @param Value[] $row 86 * @return void 87 */ 88 public function addResultRow($row) 89 { 90 $this->resultRows[] = $row; 91 } 92 93 /** 94 * Get all result rows stored in this node 95 * 96 * @return Value[][] 97 */ 98 public function getResultRows() 99 { 100 return $this->resultRows; 101 } 102 103 /** 104 * Get a unique key for this node 105 * 106 * @return string 107 */ 108 public function __toString() 109 { 110 if ($this->value === null) return ''; // root node 111 return $this->value->__toString() . '-' . $this->depth; 112 } 113 114 /** 115 * Custom comparator to sort the children of this node 116 * 117 * @param NestedValue $a 118 * @param NestedValue $b 119 * @return int 120 */ 121 public function sortChildren(NestedValue $a, NestedValue $b) 122 { 123 // note: the way NestedResults build the NestedValues, the value object should 124 // always contain a single value only. But since the associated column is still 125 // a multi-value column, getCompareValue() will still return an array. 126 // So here we treat all returns as array and join them with a dash (even though 127 // there should never be more than one value in there) 128 return Sort::strcmp( 129 join('-', (array)$a->getValueObject()->getCompareValue()), 130 join('-', (array)$b->getValueObject()->getCompareValue()) 131 ); 132 } 133 134} 135