xref: /plugin/struct/meta/AggregationList.php (revision ce44c6393fcd559a7f07942c55824e5b8379912c)
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{
12ea5ad12aSMichael Grosse
13d90aa848SAndreas Gohr    /** @var int number of all results */
14ea5ad12aSMichael Grosse    protected $resultColumnCount;
15ea5ad12aSMichael Grosse
16d90aa848SAndreas Gohr    /** @inheritdoc */
17d6d97f60SAnna Dabrowska    public function __construct($id, $mode, \Doku_Renderer $renderer, SearchConfig $searchConfig)
18d6d97f60SAnna Dabrowska    {
19d90aa848SAndreas Gohr        parent::__construct($id, $mode, $renderer, $searchConfig);
20ea5ad12aSMichael Grosse        $this->resultColumnCount = count($this->columns);
21ea5ad12aSMichael Grosse    }
22ea5ad12aSMichael Grosse
23d90aa848SAndreas Gohr    /** @inheritdoc */
24d90aa848SAndreas Gohr    public function render($showNotFound = false)
25d6d97f60SAnna Dabrowska    {
26d90aa848SAndreas Gohr        $this->startScope();
27d90aa848SAndreas Gohr        if ($this->result) {
285bc00e11SAndreas Gohr            $nestedResult = new NestedResult($this->result);
29*ce44c639SAndreas Gohr            $root = $nestedResult->getRoot($this->data['nesting'], $this->data['index']);
305bc00e11SAndreas Gohr            $this->renderNode($root);
31d90aa848SAndreas Gohr        } elseif ($showNotFound) {
32d90aa848SAndreas Gohr            $this->renderer->cdata($this->helper->getLang('none'));
33d90aa848SAndreas Gohr        }
345bc00e11SAndreas Gohr        $this->finishScope();
355bc00e11SAndreas Gohr    }
36ea5ad12aSMichael Grosse
375bc00e11SAndreas Gohr    /**
385bc00e11SAndreas Gohr     * Recursively render the result tree
395bc00e11SAndreas Gohr     *
405bc00e11SAndreas Gohr     * @param NestedValue $node
415bc00e11SAndreas Gohr     * @return void
425bc00e11SAndreas Gohr     */
435bc00e11SAndreas Gohr    protected function renderNode(NestedValue $node)
445bc00e11SAndreas Gohr    {
455bc00e11SAndreas Gohr        $self = $node->getValueObject(); // null for root node
465bc00e11SAndreas Gohr        $children = $node->getChildren();
475bc00e11SAndreas Gohr        $results = $node->getResultRows();
485bc00e11SAndreas Gohr
495bc00e11SAndreas Gohr        // all our content is in a listitem, unless we are the root node
505bc00e11SAndreas Gohr        if ($self) {
515bc00e11SAndreas Gohr            $this->renderer->listitem_open($node->getDepth() + 1); // levels are 1 based
525bc00e11SAndreas Gohr        }
535bc00e11SAndreas Gohr
545bc00e11SAndreas Gohr        // render own value if available
555bc00e11SAndreas Gohr        if ($self) {
565bc00e11SAndreas Gohr            $this->renderer->listcontent_open();
575bc00e11SAndreas Gohr            $this->renderListItem([$self], $node->getDepth()); // zero based depth
585bc00e11SAndreas Gohr            $this->renderer->listcontent_close();
595bc00e11SAndreas Gohr        }
605bc00e11SAndreas Gohr
615bc00e11SAndreas Gohr        // render children or results as sub-list
625bc00e11SAndreas Gohr        if ($children || $results) {
632c6e107cSMichael Grosse            $this->renderer->listu_open();
64ea5ad12aSMichael Grosse
655bc00e11SAndreas Gohr            foreach ($children as $child) {
665bc00e11SAndreas Gohr                $this->renderNode($child);
675bc00e11SAndreas Gohr            }
685bc00e11SAndreas Gohr
695bc00e11SAndreas Gohr            foreach ($results as $result) {
705bc00e11SAndreas Gohr                $this->renderer->listitem_open($node->getDepth() + 2); // levels are 1 based, this is one deeper
712c6e107cSMichael Grosse                $this->renderer->listcontent_open();
725bc00e11SAndreas Gohr                $this->renderListItem($result, $node->getDepth() + 1); // zero based depth, one deeper
732c6e107cSMichael Grosse                $this->renderer->listcontent_close();
742c6e107cSMichael Grosse                $this->renderer->listitem_close();
75ea5ad12aSMichael Grosse            }
76ea5ad12aSMichael Grosse
772c6e107cSMichael Grosse            $this->renderer->listu_close();
785bc00e11SAndreas Gohr        }
79ea5ad12aSMichael Grosse
805bc00e11SAndreas Gohr        // close listitem if opened
815bc00e11SAndreas Gohr        if ($self) {
825bc00e11SAndreas Gohr            $this->renderer->listitem_close();
835bc00e11SAndreas Gohr        }
84ea5ad12aSMichael Grosse    }
85ea5ad12aSMichael Grosse
86ea5ad12aSMichael Grosse    /**
87ea5ad12aSMichael Grosse     * Adds additional info to document and renderer in XHTML mode
88ea5ad12aSMichael Grosse     *
89ea5ad12aSMichael Grosse     * @see finishScope()
90ea5ad12aSMichael Grosse     */
91d6d97f60SAnna Dabrowska    protected function startScope()
92d6d97f60SAnna Dabrowska    {
93ea5ad12aSMichael Grosse        // wrapping div
94ea5ad12aSMichael Grosse        if ($this->mode != 'xhtml') return;
95ea5ad12aSMichael Grosse        $this->renderer->doc .= "<div class=\"structaggregation listaggregation\">";
96ea5ad12aSMichael Grosse    }
97ea5ad12aSMichael Grosse
98ea5ad12aSMichael Grosse    /**
99ea5ad12aSMichael Grosse     * Closes anything opened in startScope()
100ea5ad12aSMichael Grosse     *
101ea5ad12aSMichael Grosse     * @see startScope()
102ea5ad12aSMichael Grosse     */
103d6d97f60SAnna Dabrowska    protected function finishScope()
104d6d97f60SAnna Dabrowska    {
105ea5ad12aSMichael Grosse        // wrapping div
106ea5ad12aSMichael Grosse        if ($this->mode != 'xhtml') return;
107ea5ad12aSMichael Grosse        $this->renderer->doc .= '</div>';
108ea5ad12aSMichael Grosse    }
109ea5ad12aSMichael Grosse
1105bc00e11SAndreas Gohr
111ea5ad12aSMichael Grosse    /**
1125bc00e11SAndreas Gohr     * Render the content of a single list item
1135bc00e11SAndreas Gohr     *
1145bc00e11SAndreas Gohr     * @param Value[] $resultrow
1155bc00e11SAndreas Gohr     * @param int $depth The current nesting depth (zero based)
116ea5ad12aSMichael Grosse     */
1175bc00e11SAndreas Gohr    protected function renderListItem($resultrow, $depth)
118d6d97f60SAnna Dabrowska    {
119ea5ad12aSMichael Grosse        $sepbyheaders = $this->searchConfig->getConf()['sepbyheaders'];
120ea5ad12aSMichael Grosse        $headers = $this->searchConfig->getConf()['headers'];
121ea5ad12aSMichael Grosse
1225bc00e11SAndreas Gohr        foreach ($resultrow as $index => $value) {
1235bc00e11SAndreas Gohr            if ($value->isEmpty()) continue;
1245bc00e11SAndreas Gohr            $column = $index + $depth; // the resultrow is shifted by the nesting depth
125ea5ad12aSMichael Grosse            if ($sepbyheaders && !empty($headers[$column])) {
1265bc00e11SAndreas Gohr                $header = $headers[$column];
1272c6e107cSMichael Grosse            } else {
1285bc00e11SAndreas Gohr                $header = '';
1295bc00e11SAndreas Gohr            }
1305bc00e11SAndreas Gohr
1315bc00e11SAndreas Gohr            if ($this->mode === 'xhtml') {
1325bc00e11SAndreas Gohr                $this->renderValueXHTML($value, $header);
1335bc00e11SAndreas Gohr            } else {
1345bc00e11SAndreas Gohr                $this->renderValueGeneric($value, $header);
135ea5ad12aSMichael Grosse            }
1362c6e107cSMichael Grosse        }
1372c6e107cSMichael Grosse    }
1385bc00e11SAndreas Gohr
1395bc00e11SAndreas Gohr    /**
1405bc00e11SAndreas Gohr     * Render the given Value in a XHTML renderer
1415bc00e11SAndreas Gohr     * @param Value $value
1425bc00e11SAndreas Gohr     * @param string $header
1435bc00e11SAndreas Gohr     * @return void
1445bc00e11SAndreas Gohr     */
1455bc00e11SAndreas Gohr    protected function renderValueXHTML($value, $header)
1465bc00e11SAndreas Gohr    {
1475bc00e11SAndreas Gohr        $attributes = [
1485bc00e11SAndreas Gohr            'data-struct-column' => strtolower($value->getColumn()->getFullQualifiedLabel()),
1495bc00e11SAndreas Gohr            'data-struct-type' => strtolower($value->getColumn()->getType()->getClass()),
1505bc00e11SAndreas Gohr            'class' => 'li', // default dokuwiki content wrapper
1515bc00e11SAndreas Gohr        ];
1525bc00e11SAndreas Gohr
1535bc00e11SAndreas Gohr        $this->renderer->doc .= sprintf('<div %s>', buildAttributes($attributes)); // wrapper
1545bc00e11SAndreas Gohr        if ($header !== '') {
1555bc00e11SAndreas Gohr            $this->renderer->doc .= sprintf('<span class="struct_header">%s</span> ', hsc($header));
1565bc00e11SAndreas Gohr        }
1575bc00e11SAndreas Gohr        $this->renderer->doc .= '<div class="struct_value">';
158ea5ad12aSMichael Grosse        $value->render($this->renderer, $this->mode);
159ea5ad12aSMichael Grosse        $this->renderer->doc .= '</div>';
1605bc00e11SAndreas Gohr        $this->renderer->doc .= '</div> '; // wrapper
161ea5ad12aSMichael Grosse    }
1625bc00e11SAndreas Gohr
1635bc00e11SAndreas Gohr    /**
1645bc00e11SAndreas Gohr     * Render the given Value in any non-XHTML renderer
1655bc00e11SAndreas Gohr     * @param Value $value
1665bc00e11SAndreas Gohr     * @param string $header
1675bc00e11SAndreas Gohr     * @return void
1685bc00e11SAndreas Gohr     */
1695bc00e11SAndreas Gohr    protected function renderValueGeneric($value, $header)
1705bc00e11SAndreas Gohr    {
1715bc00e11SAndreas Gohr        $this->renderer->listcontent_open();
1725bc00e11SAndreas Gohr        if ($header !== '') $this->renderer->cdata($header . ' ');
1735bc00e11SAndreas Gohr        $value->render($this->renderer, $this->mode);
1745bc00e11SAndreas Gohr        $this->renderer->listcontent_close();
175ea5ad12aSMichael Grosse    }
176ea5ad12aSMichael Grosse}
177