Files
dokuwiki-plugin-struct/meta/AggregationList.php
2024-02-06 10:03:36 +01:00

163 lines
5.5 KiB
PHP

<?php
namespace dokuwiki\plugin\struct\meta;
/**
* Class AggregationList
*
* @package dokuwiki\plugin\struct\meta
*/
class AggregationList extends Aggregation
{
/** @var int number of all results */
protected $resultColumnCount;
/** @inheritdoc */
public function __construct($id, $mode, \Doku_Renderer $renderer, SearchConfig $searchConfig)
{
parent::__construct($id, $mode, $renderer, $searchConfig);
$this->resultColumnCount = count($this->columns);
}
/** @inheritdoc */
public function render($showNotFound = false)
{
if ($this->searchConfig->getResult()) {
$nestedResult = new NestedResult($this->searchConfig->getRows());
$root = $nestedResult->getRoot($this->data['nesting'], $this->data['index']);
$this->renderNode($root);
} elseif ($showNotFound) {
$this->renderer->cdata($this->helper->getLang('none'));
}
}
/**
* Recursively render the result tree
*
* @param NestedValue $node
* @return void
*/
protected function renderNode(NestedValue $node)
{
$self = $node->getValueObject(); // null for root node
$children = $node->getChildren(!$self instanceof Value && $this->data['index']); // sort only for index
$results = $node->getResultRows();
// all our content is in a listitem, unless we are the root node
if ($self instanceof Value) {
$this->renderer->listitem_open($node->getDepth() + 1); // levels are 1 based
}
// render own value if available
if ($self instanceof Value) {
$this->renderer->listcontent_open();
$this->renderListItem([$self], $node->getDepth(), true); // zero based depth
$this->renderer->listcontent_close();
}
// render children or results as sub-list
if ($children || $results) {
$this->renderer->listu_open();
foreach ($children as $child) {
$this->renderNode($child);
}
foreach ($results as $result) {
$this->renderer->listitem_open($node->getDepth() + 2); // levels are 1 based, this is one deeper
$this->renderer->listcontent_open();
$this->renderListItem($result, $node->getDepth() + 1); // zero based depth, one deeper
$this->renderer->listcontent_close();
$this->renderer->listitem_close();
}
$this->renderer->listu_close();
}
// close listitem if opened
if ($self instanceof Value) {
$this->renderer->listitem_close();
}
}
/**
* Render the content of a single list item
*
* @param Value[] $resultrow
* @param int $depth The current nesting depth (zero based)
* @param bool $showEmpty show a placeholder for empty values?
*/
protected function renderListItem($resultrow, $depth, $showEmpty = false)
{
$config = $this->searchConfig->getConf();
$sepbyheaders = $config['sepbyheaders'];
$headers = $config['headers'];
foreach ($resultrow as $index => $value) {
// when nesting, the resultrow is shifted by the nesting depth
$column = $index;
if ($config['nesting']) {
$column += $depth;
}
if ($sepbyheaders && !empty($headers[$column])) {
$header = $headers[$column];
} else {
$header = '';
}
if ($this->mode === 'xhtml') {
$this->renderValueXHTML($value, $header, $showEmpty);
} else {
$this->renderValueGeneric($value, $header, $showEmpty);
}
}
}
/**
* Render the given Value in a XHTML renderer
* @param Value $value
* @param string $header
* @param bool $showEmpty
* @return void
*/
protected function renderValueXHTML($value, $header, $showEmpty = false)
{
$attributes = [
'data-struct-column' => strtolower($value->getColumn()->getFullQualifiedLabel()),
'data-struct-type' => strtolower($value->getColumn()->getType()->getClass()),
'class' => 'li', // default dokuwiki content wrapper
];
$this->renderer->doc .= sprintf('<div %s>', buildAttributes($attributes)); // wrapper
if ($header !== '') {
$this->renderer->doc .= sprintf('<span class="struct_header">%s</span> ', hsc($header));
}
$this->renderer->doc .= '<div class="struct_value">';
if ($value->isEmpty() && $showEmpty) {
$this->renderer->doc .= '<span class="struct_na">' . $this->helper->getLang('na') . '</span>';
} else {
$value->render($this->renderer, $this->mode);
}
$this->renderer->doc .= '</div>';
$this->renderer->doc .= '</div> '; // wrapper
}
/**
* Render the given Value in any non-XHTML renderer
* @param Value $value
* @param string $header
* @return void
*/
protected function renderValueGeneric($value, $header, $showEmpty = false)
{
$this->renderer->listcontent_open();
if ($header !== '') $this->renderer->cdata($header . ' ');
if ($value->isEmpty() && $showEmpty) {
$this->renderer->cdata($this->helper->getLang('na'));
} else {
$value->render($this->renderer, $this->mode);
}
$this->renderer->listcontent_close();
}
}