xref: /plugin/struct/meta/AggregationFilter.php (revision fdf371159b3e9f57726cdb9c44df35e764a8770a)
1<?php
2
3namespace dokuwiki\plugin\struct\meta;
4
5use dokuwiki\Form\Form;
6use dokuwiki\Utf8\Sort;
7
8/**
9 * Struct filter class
10 */
11class AggregationFilter extends Aggregation
12{
13    /**
14     * Render the filter form.
15     * Reuses the structure of advanced search tools to leverage
16     * the core grouping styles and scripts.
17     *
18     * @param bool $showNotFound Inherited from parent method
19     * @return void
20     */
21    public function render($showNotFound = false)
22    {
23        $colValues = $this->getAllColumnValues($this->result);
24
25        // column dropdowns
26        foreach ($colValues as $num => $colData) {
27            /** @var Column $column */
28            $column = $colData['column'];
29
30            $this->renderer->doc .= '<details>';
31            $this->renderer->doc .= '<summary>' . hsc($colData['label']) . '</summary>';
32            $this->renderer->doc .= '<ul>';
33            foreach ($colData['values'] as $value => $displayValue) {
34                $current = false;
35                $dyn = $this->searchConfig->getDynamicParameters();
36                $allFilters = $dyn->getFilters();
37                if (isset($allFilters[$column->getFullQualifiedLabel()])) {
38                    if ($allFilters[$column->getFullQualifiedLabel()][1] == $displayValue) {
39                        $current = true;
40                    }
41                    $dyn->removeFilter($column); // remove previous filter for this column
42                }
43                if (!$current) {
44                    // add new filter unless it's the current item
45                    $dyn->addFilter($column, '=', $displayValue);
46                }
47                $params = $dyn->getURLParameters();
48                $filter = buildURLparams($params);
49
50                $this->renderer->doc .= '<li ' . ($current ? 'class="active"' : '') . '><div class="li">';
51                $column->getType()->renderTagCloudLink($value, $this->renderer, $this->mode, $this->id, $filter, 100);
52                $this->renderer->doc .= '</div></li>';
53            }
54            $this->renderer->doc .= '</ul>';
55            $this->renderer->doc .= '</details>';
56        }
57    }
58
59    /**
60     * Get all values from given search result grouped by column
61     *
62     * @return array
63     */
64    protected function getAllColumnValues($result)
65    {
66        $colValues = [];
67
68        foreach ($result as $row) {
69            foreach ($row as $value) {
70                /** @var Value $value */
71                $colName = $value->getColumn()->getFullQualifiedLabel();
72                $colValues[$colName]['column'] = $value->getColumn();
73                $colValues[$colName]['label'] = $value->getColumn()->getTranslatedLabel();
74                $colValues[$colName]['values'] = $colValues[$colName]['values'] ?? [];
75
76                if (empty($value->getDisplayValue())) continue;
77
78                // create an array with [value => displayValue] pairs
79                // the cast to array will handle single and multi-value fields the same
80                // using the full value as key will make sure we don't have duplicates
81                $pairs = array_combine((array)$value->getValue(), (array)$value->getDisplayValue());
82                $colValues[$colName]['values'] = array_merge($colValues[$colName]['values'], $pairs);
83            }
84        }
85
86        // sort by display value
87        array_walk($colValues, function (&$col) {
88            Sort::asort($col['values']);
89        });
90
91        return array_values($colValues); // reindex
92    }
93}
94