xref: /plugin/struct/meta/AggregationList.php (revision 62c804cc11db5ad59330873e041f0294e4b72688)
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
437234bfb1Ssplitbrain        $children = $node->getChildren(!$self instanceof Value && $this->data['index']); // sort only for index
445bc00e11SAndreas Gohr        $results = $node->getResultRows();
455bc00e11SAndreas Gohr
465bc00e11SAndreas Gohr        // all our content is in a listitem, unless we are the root node
477234bfb1Ssplitbrain        if ($self instanceof Value) {
485bc00e11SAndreas Gohr            $this->renderer->listitem_open($node->getDepth() + 1); // levels are 1 based
495bc00e11SAndreas Gohr        }
505bc00e11SAndreas Gohr
515bc00e11SAndreas Gohr        // render own value if available
527234bfb1Ssplitbrain        if ($self instanceof Value) {
535bc00e11SAndreas Gohr            $this->renderer->listcontent_open();
547b7a9290SAndreas 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
787234bfb1Ssplitbrain        if ($self instanceof Value) {
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)
887b7a9290SAndreas Gohr     * @param bool $showEmpty show a placeholder for empty values?
89ea5ad12aSMichael Grosse     */
907b7a9290SAndreas Gohr    protected function renderListItem($resultrow, $depth, $showEmpty = false)
91d6d97f60SAnna Dabrowska    {
92*62c804ccSAnna Dabrowska        $config = $this->searchConfig->getConf();
93*62c804ccSAnna Dabrowska        $sepbyheaders = $config['sepbyheaders'];
94*62c804ccSAnna Dabrowska        $headers = $config['headers'];
95ea5ad12aSMichael Grosse
965bc00e11SAndreas Gohr        foreach ($resultrow as $index => $value) {
97*62c804ccSAnna Dabrowska            // when nesting, the resultrow is shifted by the nesting depth
98*62c804ccSAnna Dabrowska            $column = $index;
99*62c804ccSAnna Dabrowska            if ($config['nesting']) {
100*62c804ccSAnna Dabrowska                $column += $depth;
101*62c804ccSAnna Dabrowska            }
102ea5ad12aSMichael Grosse            if ($sepbyheaders && !empty($headers[$column])) {
1035bc00e11SAndreas Gohr                $header = $headers[$column];
1042c6e107cSMichael Grosse            } else {
1055bc00e11SAndreas Gohr                $header = '';
1065bc00e11SAndreas Gohr            }
1075bc00e11SAndreas Gohr
1085bc00e11SAndreas Gohr            if ($this->mode === 'xhtml') {
1097b7a9290SAndreas Gohr                $this->renderValueXHTML($value, $header, $showEmpty);
1105bc00e11SAndreas Gohr            } else {
1117b7a9290SAndreas Gohr                $this->renderValueGeneric($value, $header, $showEmpty);
112ea5ad12aSMichael Grosse            }
1132c6e107cSMichael Grosse        }
1142c6e107cSMichael Grosse    }
1155bc00e11SAndreas Gohr
1165bc00e11SAndreas Gohr    /**
1175bc00e11SAndreas Gohr     * Render the given Value in a XHTML renderer
1185bc00e11SAndreas Gohr     * @param Value $value
1195bc00e11SAndreas Gohr     * @param string $header
1207b7a9290SAndreas Gohr     * @param bool $showEmpty
1215bc00e11SAndreas Gohr     * @return void
1225bc00e11SAndreas Gohr     */
1237b7a9290SAndreas Gohr    protected function renderValueXHTML($value, $header, $showEmpty = false)
1245bc00e11SAndreas Gohr    {
1255bc00e11SAndreas Gohr        $attributes = [
1265bc00e11SAndreas Gohr            'data-struct-column' => strtolower($value->getColumn()->getFullQualifiedLabel()),
1275bc00e11SAndreas Gohr            'data-struct-type' => strtolower($value->getColumn()->getType()->getClass()),
1285bc00e11SAndreas Gohr            'class' => 'li', // default dokuwiki content wrapper
1295bc00e11SAndreas Gohr        ];
1305bc00e11SAndreas Gohr
1315bc00e11SAndreas Gohr        $this->renderer->doc .= sprintf('<div %s>', buildAttributes($attributes)); // wrapper
1325bc00e11SAndreas Gohr        if ($header !== '') {
1335bc00e11SAndreas Gohr            $this->renderer->doc .= sprintf('<span class="struct_header">%s</span> ', hsc($header));
1345bc00e11SAndreas Gohr        }
1355bc00e11SAndreas Gohr        $this->renderer->doc .= '<div class="struct_value">';
1367b7a9290SAndreas Gohr        if ($value->isEmpty() && $showEmpty) {
1377b7a9290SAndreas Gohr            $this->renderer->doc .= '<span class="struct_na">' . $this->helper->getLang('na') . '</span>';
1387b7a9290SAndreas Gohr        } else {
139ea5ad12aSMichael Grosse            $value->render($this->renderer, $this->mode);
1407b7a9290SAndreas Gohr        }
141ea5ad12aSMichael Grosse        $this->renderer->doc .= '</div>';
1425bc00e11SAndreas Gohr        $this->renderer->doc .= '</div> '; // wrapper
143ea5ad12aSMichael Grosse    }
1445bc00e11SAndreas Gohr
1455bc00e11SAndreas Gohr    /**
1465bc00e11SAndreas Gohr     * Render the given Value in any non-XHTML renderer
1475bc00e11SAndreas Gohr     * @param Value $value
1485bc00e11SAndreas Gohr     * @param string $header
1495bc00e11SAndreas Gohr     * @return void
1505bc00e11SAndreas Gohr     */
1517b7a9290SAndreas Gohr    protected function renderValueGeneric($value, $header, $showEmpty = false)
1525bc00e11SAndreas Gohr    {
1535bc00e11SAndreas Gohr        $this->renderer->listcontent_open();
1545bc00e11SAndreas Gohr        if ($header !== '') $this->renderer->cdata($header . ' ');
1557b7a9290SAndreas Gohr        if ($value->isEmpty() && $showEmpty) {
1567b7a9290SAndreas Gohr            $this->renderer->cdata($this->helper->getLang('na'));
1577b7a9290SAndreas Gohr        } else {
1585bc00e11SAndreas Gohr            $value->render($this->renderer, $this->mode);
1597b7a9290SAndreas Gohr        }
1605bc00e11SAndreas Gohr        $this->renderer->listcontent_close();
161ea5ad12aSMichael Grosse    }
162ea5ad12aSMichael Grosse}
163