1<?php 2 3namespace dokuwiki\plugin\struct\meta; 4 5/** 6 * Class AggregationList 7 * 8 * @package dokuwiki\plugin\struct\meta 9 */ 10class AggregationList extends Aggregation 11{ 12 /** @var int number of all results */ 13 protected $resultColumnCount; 14 15 /** @inheritdoc */ 16 public function __construct($id, $mode, \Doku_Renderer $renderer, SearchConfig $searchConfig) 17 { 18 parent::__construct($id, $mode, $renderer, $searchConfig); 19 $this->resultColumnCount = count($this->columns); 20 } 21 22 /** @inheritdoc */ 23 public function render($showNotFound = false) 24 { 25 if ($this->result) { 26 $nestedResult = new NestedResult($this->result); 27 $root = $nestedResult->getRoot($this->data['nesting'], $this->data['index']); 28 $this->renderNode($root); 29 } elseif ($showNotFound) { 30 $this->renderer->cdata($this->helper->getLang('none')); 31 } 32 } 33 34 /** 35 * Recursively render the result tree 36 * 37 * @param NestedValue $node 38 * @return void 39 */ 40 protected function renderNode(NestedValue $node) 41 { 42 $self = $node->getValueObject(); // null for root node 43 $children = $node->getChildren(); 44 $results = $node->getResultRows(); 45 46 // all our content is in a listitem, unless we are the root node 47 if ($self) { 48 $this->renderer->listitem_open($node->getDepth() + 1); // levels are 1 based 49 } 50 51 // render own value if available 52 if ($self) { 53 $this->renderer->listcontent_open(); 54 $this->renderListItem([$self], $node->getDepth()); // zero based depth 55 $this->renderer->listcontent_close(); 56 } 57 58 // render children or results as sub-list 59 if ($children || $results) { 60 $this->renderer->listu_open(); 61 62 foreach ($children as $child) { 63 $this->renderNode($child); 64 } 65 66 foreach ($results as $result) { 67 $this->renderer->listitem_open($node->getDepth() + 2); // levels are 1 based, this is one deeper 68 $this->renderer->listcontent_open(); 69 $this->renderListItem($result, $node->getDepth() + 1); // zero based depth, one deeper 70 $this->renderer->listcontent_close(); 71 $this->renderer->listitem_close(); 72 } 73 74 $this->renderer->listu_close(); 75 } 76 77 // close listitem if opened 78 if ($self) { 79 $this->renderer->listitem_close(); 80 } 81 } 82 83 /** 84 * Render the content of a single list item 85 * 86 * @param Value[] $resultrow 87 * @param int $depth The current nesting depth (zero based) 88 */ 89 protected function renderListItem($resultrow, $depth) 90 { 91 $sepbyheaders = $this->searchConfig->getConf()['sepbyheaders']; 92 $headers = $this->searchConfig->getConf()['headers']; 93 94 foreach ($resultrow as $index => $value) { 95 if ($value->isEmpty()) continue; 96 $column = $index + $depth; // the resultrow is shifted by the nesting depth 97 if ($sepbyheaders && !empty($headers[$column])) { 98 $header = $headers[$column]; 99 } else { 100 $header = ''; 101 } 102 103 if ($this->mode === 'xhtml') { 104 $this->renderValueXHTML($value, $header); 105 } else { 106 $this->renderValueGeneric($value, $header); 107 } 108 } 109 } 110 111 /** 112 * Render the given Value in a XHTML renderer 113 * @param Value $value 114 * @param string $header 115 * @return void 116 */ 117 protected function renderValueXHTML($value, $header) 118 { 119 $attributes = [ 120 'data-struct-column' => strtolower($value->getColumn()->getFullQualifiedLabel()), 121 'data-struct-type' => strtolower($value->getColumn()->getType()->getClass()), 122 'class' => 'li', // default dokuwiki content wrapper 123 ]; 124 125 $this->renderer->doc .= sprintf('<div %s>', buildAttributes($attributes)); // wrapper 126 if ($header !== '') { 127 $this->renderer->doc .= sprintf('<span class="struct_header">%s</span> ', hsc($header)); 128 } 129 $this->renderer->doc .= '<div class="struct_value">'; 130 $value->render($this->renderer, $this->mode); 131 $this->renderer->doc .= '</div>'; 132 $this->renderer->doc .= '</div> '; // wrapper 133 } 134 135 /** 136 * Render the given Value in any non-XHTML renderer 137 * @param Value $value 138 * @param string $header 139 * @return void 140 */ 141 protected function renderValueGeneric($value, $header) 142 { 143 $this->renderer->listcontent_open(); 144 if ($header !== '') $this->renderer->cdata($header . ' '); 145 $value->render($this->renderer, $this->mode); 146 $this->renderer->listcontent_close(); 147 } 148} 149