1ea5ad12aSMichael Grosse<?php 2ea5ad12aSMichael Grosse 3ea5ad12aSMichael Grossenamespace dokuwiki\plugin\struct\meta; 4ea5ad12aSMichael Grosse 5ea5ad12aSMichael Grosse/** 6ea5ad12aSMichael Grosse * Class AggregationList 7ea5ad12aSMichael Grosse * 8ea5ad12aSMichael Grosse * @package dokuwiki\plugin\struct\meta 9ea5ad12aSMichael Grosse */ 10d90aa848SAndreas Gohrclass AggregationList extends Aggregation 11d6d97f60SAnna Dabrowska{ 12d90aa848SAndreas Gohr /** @var int number of all results */ 13ea5ad12aSMichael Grosse protected $resultColumnCount; 14ea5ad12aSMichael Grosse 15d90aa848SAndreas Gohr /** @inheritdoc */ 16d6d97f60SAnna Dabrowska public function __construct($id, $mode, \Doku_Renderer $renderer, SearchConfig $searchConfig) 17d6d97f60SAnna Dabrowska { 18d90aa848SAndreas Gohr parent::__construct($id, $mode, $renderer, $searchConfig); 19ea5ad12aSMichael Grosse $this->resultColumnCount = count($this->columns); 20ea5ad12aSMichael Grosse } 21ea5ad12aSMichael Grosse 22d90aa848SAndreas Gohr /** @inheritdoc */ 23d90aa848SAndreas Gohr public function render($showNotFound = false) 24d6d97f60SAnna Dabrowska { 25d90aa848SAndreas Gohr if ($this->result) { 265bc00e11SAndreas Gohr $nestedResult = new NestedResult($this->result); 27ce44c639SAndreas Gohr $root = $nestedResult->getRoot($this->data['nesting'], $this->data['index']); 285bc00e11SAndreas Gohr $this->renderNode($root); 29d90aa848SAndreas Gohr } elseif ($showNotFound) { 30d90aa848SAndreas Gohr $this->renderer->cdata($this->helper->getLang('none')); 31d90aa848SAndreas Gohr } 325bc00e11SAndreas Gohr } 33ea5ad12aSMichael Grosse 345bc00e11SAndreas Gohr /** 355bc00e11SAndreas Gohr * Recursively render the result tree 365bc00e11SAndreas Gohr * 375bc00e11SAndreas Gohr * @param NestedValue $node 385bc00e11SAndreas Gohr * @return void 395bc00e11SAndreas Gohr */ 405bc00e11SAndreas Gohr protected function renderNode(NestedValue $node) 415bc00e11SAndreas Gohr { 425bc00e11SAndreas Gohr $self = $node->getValueObject(); // null for root node 435bc00e11SAndreas Gohr $children = $node->getChildren(); 445bc00e11SAndreas Gohr $results = $node->getResultRows(); 455bc00e11SAndreas Gohr 465bc00e11SAndreas Gohr // all our content is in a listitem, unless we are the root node 475bc00e11SAndreas Gohr if ($self) { 485bc00e11SAndreas Gohr $this->renderer->listitem_open($node->getDepth() + 1); // levels are 1 based 495bc00e11SAndreas Gohr } 505bc00e11SAndreas Gohr 515bc00e11SAndreas Gohr // render own value if available 525bc00e11SAndreas Gohr if ($self) { 535bc00e11SAndreas Gohr $this->renderer->listcontent_open(); 54*7b7a9290SAndreas Gohr $this->renderListItem([$self], $node->getDepth(), true); // zero based depth 555bc00e11SAndreas Gohr $this->renderer->listcontent_close(); 565bc00e11SAndreas Gohr } 575bc00e11SAndreas Gohr 585bc00e11SAndreas Gohr // render children or results as sub-list 595bc00e11SAndreas Gohr if ($children || $results) { 602c6e107cSMichael Grosse $this->renderer->listu_open(); 61ea5ad12aSMichael Grosse 625bc00e11SAndreas Gohr foreach ($children as $child) { 635bc00e11SAndreas Gohr $this->renderNode($child); 645bc00e11SAndreas Gohr } 655bc00e11SAndreas Gohr 665bc00e11SAndreas Gohr foreach ($results as $result) { 675bc00e11SAndreas Gohr $this->renderer->listitem_open($node->getDepth() + 2); // levels are 1 based, this is one deeper 682c6e107cSMichael Grosse $this->renderer->listcontent_open(); 695bc00e11SAndreas Gohr $this->renderListItem($result, $node->getDepth() + 1); // zero based depth, one deeper 702c6e107cSMichael Grosse $this->renderer->listcontent_close(); 712c6e107cSMichael Grosse $this->renderer->listitem_close(); 72ea5ad12aSMichael Grosse } 73ea5ad12aSMichael Grosse 742c6e107cSMichael Grosse $this->renderer->listu_close(); 755bc00e11SAndreas Gohr } 76ea5ad12aSMichael Grosse 775bc00e11SAndreas Gohr // close listitem if opened 785bc00e11SAndreas Gohr if ($self) { 795bc00e11SAndreas Gohr $this->renderer->listitem_close(); 805bc00e11SAndreas Gohr } 81ea5ad12aSMichael Grosse } 82ea5ad12aSMichael Grosse 83ea5ad12aSMichael Grosse /** 845bc00e11SAndreas Gohr * Render the content of a single list item 855bc00e11SAndreas Gohr * 865bc00e11SAndreas Gohr * @param Value[] $resultrow 875bc00e11SAndreas Gohr * @param int $depth The current nesting depth (zero based) 88*7b7a9290SAndreas Gohr * @param bool $showEmpty show a placeholder for empty values? 89ea5ad12aSMichael Grosse */ 90*7b7a9290SAndreas Gohr protected function renderListItem($resultrow, $depth, $showEmpty = false) 91d6d97f60SAnna Dabrowska { 92ea5ad12aSMichael Grosse $sepbyheaders = $this->searchConfig->getConf()['sepbyheaders']; 93ea5ad12aSMichael Grosse $headers = $this->searchConfig->getConf()['headers']; 94ea5ad12aSMichael Grosse 955bc00e11SAndreas Gohr foreach ($resultrow as $index => $value) { 965bc00e11SAndreas Gohr $column = $index + $depth; // the resultrow is shifted by the nesting depth 97ea5ad12aSMichael Grosse if ($sepbyheaders && !empty($headers[$column])) { 985bc00e11SAndreas Gohr $header = $headers[$column]; 992c6e107cSMichael Grosse } else { 1005bc00e11SAndreas Gohr $header = ''; 1015bc00e11SAndreas Gohr } 1025bc00e11SAndreas Gohr 1035bc00e11SAndreas Gohr if ($this->mode === 'xhtml') { 104*7b7a9290SAndreas Gohr $this->renderValueXHTML($value, $header, $showEmpty); 1055bc00e11SAndreas Gohr } else { 106*7b7a9290SAndreas Gohr $this->renderValueGeneric($value, $header, $showEmpty); 107ea5ad12aSMichael Grosse } 1082c6e107cSMichael Grosse } 1092c6e107cSMichael Grosse } 1105bc00e11SAndreas Gohr 1115bc00e11SAndreas Gohr /** 1125bc00e11SAndreas Gohr * Render the given Value in a XHTML renderer 1135bc00e11SAndreas Gohr * @param Value $value 1145bc00e11SAndreas Gohr * @param string $header 115*7b7a9290SAndreas Gohr * @param bool $showEmpty 1165bc00e11SAndreas Gohr * @return void 1175bc00e11SAndreas Gohr */ 118*7b7a9290SAndreas Gohr protected function renderValueXHTML($value, $header, $showEmpty = false) 1195bc00e11SAndreas Gohr { 1205bc00e11SAndreas Gohr $attributes = [ 1215bc00e11SAndreas Gohr 'data-struct-column' => strtolower($value->getColumn()->getFullQualifiedLabel()), 1225bc00e11SAndreas Gohr 'data-struct-type' => strtolower($value->getColumn()->getType()->getClass()), 1235bc00e11SAndreas Gohr 'class' => 'li', // default dokuwiki content wrapper 1245bc00e11SAndreas Gohr ]; 1255bc00e11SAndreas Gohr 1265bc00e11SAndreas Gohr $this->renderer->doc .= sprintf('<div %s>', buildAttributes($attributes)); // wrapper 1275bc00e11SAndreas Gohr if ($header !== '') { 1285bc00e11SAndreas Gohr $this->renderer->doc .= sprintf('<span class="struct_header">%s</span> ', hsc($header)); 1295bc00e11SAndreas Gohr } 1305bc00e11SAndreas Gohr $this->renderer->doc .= '<div class="struct_value">'; 131*7b7a9290SAndreas Gohr if ($value->isEmpty() && $showEmpty) { 132*7b7a9290SAndreas Gohr $this->renderer->doc .= '<span class="struct_na">' . $this->helper->getLang('na') . '</span>'; 133*7b7a9290SAndreas Gohr } else { 134ea5ad12aSMichael Grosse $value->render($this->renderer, $this->mode); 135*7b7a9290SAndreas Gohr } 136ea5ad12aSMichael Grosse $this->renderer->doc .= '</div>'; 1375bc00e11SAndreas Gohr $this->renderer->doc .= '</div> '; // wrapper 138ea5ad12aSMichael Grosse } 1395bc00e11SAndreas Gohr 1405bc00e11SAndreas Gohr /** 1415bc00e11SAndreas Gohr * Render the given Value in any non-XHTML renderer 1425bc00e11SAndreas Gohr * @param Value $value 1435bc00e11SAndreas Gohr * @param string $header 1445bc00e11SAndreas Gohr * @return void 1455bc00e11SAndreas Gohr */ 146*7b7a9290SAndreas Gohr protected function renderValueGeneric($value, $header, $showEmpty = false) 1475bc00e11SAndreas Gohr { 1485bc00e11SAndreas Gohr $this->renderer->listcontent_open(); 1495bc00e11SAndreas Gohr if ($header !== '') $this->renderer->cdata($header . ' '); 150*7b7a9290SAndreas Gohr if ($value->isEmpty() && $showEmpty) { 151*7b7a9290SAndreas Gohr $this->renderer->cdata($this->helper->getLang('na')); 152*7b7a9290SAndreas Gohr } else { 1535bc00e11SAndreas Gohr $value->render($this->renderer, $this->mode); 154*7b7a9290SAndreas Gohr } 1555bc00e11SAndreas Gohr $this->renderer->listcontent_close(); 156ea5ad12aSMichael Grosse } 157ea5ad12aSMichael Grosse} 158