xref: /plugin/struct/meta/AggregationFilter.php (revision 267f116487b4b90022958417b73b517ce79b206c)
1f1812f0bSAndreas Gohr<?php
2f1812f0bSAndreas Gohr
3f1812f0bSAndreas Gohrnamespace dokuwiki\plugin\struct\meta;
4f1812f0bSAndreas Gohr
5f1812f0bSAndreas Gohruse dokuwiki\Form\Form;
6f1812f0bSAndreas Gohruse dokuwiki\Utf8\Sort;
7f1812f0bSAndreas Gohr
8f1812f0bSAndreas Gohr/**
9f1812f0bSAndreas Gohr * Struct filter class
10f1812f0bSAndreas Gohr */
11f1812f0bSAndreas Gohrclass AggregationFilter extends Aggregation
12f1812f0bSAndreas Gohr{
13f1812f0bSAndreas Gohr    /**
14f1812f0bSAndreas Gohr     * Render the filter form.
15f1812f0bSAndreas Gohr     * Reuses the structure of advanced search tools to leverage
16f1812f0bSAndreas Gohr     * the core grouping styles and scripts.
17f1812f0bSAndreas Gohr     *
18f1812f0bSAndreas Gohr     * @param bool $showNotFound Inherited from parent method
19f1812f0bSAndreas Gohr     * @return void
20f1812f0bSAndreas Gohr     */
21f1812f0bSAndreas Gohr    public function render($showNotFound = false)
22f1812f0bSAndreas Gohr    {
23*267f1164SAndreas Gohr        $colValues = $this->getAllColumnValues($this->searchConfig->getResult()->getRows());
24f1812f0bSAndreas Gohr
25f1812f0bSAndreas Gohr        // column dropdowns
26bea7239dSAndreas Gohr        foreach ($colValues as $num => $colData) {
27bea7239dSAndreas Gohr            /** @var Column $column */
28bea7239dSAndreas Gohr            $column = $colData['column'];
29457017d1SAndreas Gohr            $label = $this->data['headers'][$num] ?? $colData['label'];
30f1812f0bSAndreas Gohr
31bea7239dSAndreas Gohr            $this->renderer->doc .= '<details>';
32457017d1SAndreas Gohr            $this->renderer->doc .= '<summary>' . hsc($label) . '</summary>';
33bea7239dSAndreas Gohr            $this->renderer->doc .= '<ul>';
34bea7239dSAndreas Gohr            foreach ($colData['values'] as $value => $displayValue) {
350ebf3045SAndreas Gohr                $current = false;
36fd9c77d3SAndreas Gohr                $dyn = $this->searchConfig->getDynamicParameters();
370ebf3045SAndreas Gohr                $allFilters = $dyn->getFilters();
380ebf3045SAndreas Gohr                if (isset($allFilters[$column->getFullQualifiedLabel()])) {
390ebf3045SAndreas Gohr                    if ($allFilters[$column->getFullQualifiedLabel()][1] == $displayValue) {
400ebf3045SAndreas Gohr                        $current = true;
410ebf3045SAndreas Gohr                    }
420ebf3045SAndreas Gohr                    $dyn->removeFilter($column); // remove previous filter for this column
430ebf3045SAndreas Gohr                }
440ebf3045SAndreas Gohr                if (!$current) {
450ebf3045SAndreas Gohr                    // add new filter unless it's the current item
46fd9c77d3SAndreas Gohr                    $dyn->addFilter($column, '=', $displayValue);
470ebf3045SAndreas Gohr                }
48fd9c77d3SAndreas Gohr                $params = $dyn->getURLParameters();
49fd9c77d3SAndreas Gohr                $filter = buildURLparams($params);
50fd9c77d3SAndreas Gohr
510ebf3045SAndreas Gohr                $this->renderer->doc .= '<li ' . ($current ? 'class="active"' : '') . '><div class="li">';
52bea7239dSAndreas Gohr                $column->getType()->renderTagCloudLink($value, $this->renderer, $this->mode, $this->id, $filter, 100);
53bea7239dSAndreas Gohr                $this->renderer->doc .= '</div></li>';
54f1812f0bSAndreas Gohr            }
55bea7239dSAndreas Gohr            $this->renderer->doc .= '</ul>';
56bea7239dSAndreas Gohr            $this->renderer->doc .= '</details>';
57f1812f0bSAndreas Gohr        }
58f1812f0bSAndreas Gohr    }
59f1812f0bSAndreas Gohr
60f1812f0bSAndreas Gohr    /**
61f1812f0bSAndreas Gohr     * Get all values from given search result grouped by column
62f1812f0bSAndreas Gohr     *
63f1812f0bSAndreas Gohr     * @return array
64f1812f0bSAndreas Gohr     */
65f1812f0bSAndreas Gohr    protected function getAllColumnValues($result)
66f1812f0bSAndreas Gohr    {
67f1812f0bSAndreas Gohr        $colValues = [];
68f1812f0bSAndreas Gohr
69f1812f0bSAndreas Gohr        foreach ($result as $row) {
70f1812f0bSAndreas Gohr            foreach ($row as $value) {
71f1812f0bSAndreas Gohr                /** @var Value $value */
72f1812f0bSAndreas Gohr                $colName = $value->getColumn()->getFullQualifiedLabel();
73bea7239dSAndreas Gohr                $colValues[$colName]['column'] = $value->getColumn();
74f1812f0bSAndreas Gohr                $colValues[$colName]['label'] = $value->getColumn()->getTranslatedLabel();
755e29103aSannda                $colValues[$colName]['values'] ??= [];
76f1812f0bSAndreas Gohr
77bea7239dSAndreas Gohr                if (empty($value->getDisplayValue())) continue;
78f1812f0bSAndreas Gohr
79bea7239dSAndreas Gohr                // create an array with [value => displayValue] pairs
80bea7239dSAndreas Gohr                // the cast to array will handle single and multi-value fields the same
81bea7239dSAndreas Gohr                // using the full value as key will make sure we don't have duplicates
82da8d86adSAndreas Gohr                //
83da8d86adSAndreas Gohr                // because a value might be interpreted as integer in the array key, we pad
84da8d86adSAndreas Gohr                // each key with a space at the end to enforce string keys. The space will
85da8d86adSAndreas Gohr                // be ignored when parsing JSON values and trimmed for all other types.
86da8d86adSAndreas Gohr                // This is a work around for #665
87da8d86adSAndreas Gohr                $pairs = array_combine(
88da8d86adSAndreas Gohr                    array_map(
89da8d86adSAndreas Gohr                        static fn($v) => "$v ",
90da8d86adSAndreas Gohr                        (array)$value->getValue()
91da8d86adSAndreas Gohr                    ),
92da8d86adSAndreas Gohr                    (array)$value->getDisplayValue()
93da8d86adSAndreas Gohr                );
94bea7239dSAndreas Gohr                $colValues[$colName]['values'] = array_merge($colValues[$colName]['values'], $pairs);
95f1812f0bSAndreas Gohr            }
96f1812f0bSAndreas Gohr        }
97f1812f0bSAndreas Gohr
98bea7239dSAndreas Gohr        // sort by display value
99f1812f0bSAndreas Gohr        array_walk($colValues, function (&$col) {
100bea7239dSAndreas Gohr            Sort::asort($col['values']);
101f1812f0bSAndreas Gohr        });
102f1812f0bSAndreas Gohr
103bea7239dSAndreas Gohr        return array_values($colValues); // reindex
104f1812f0bSAndreas Gohr    }
105f1812f0bSAndreas Gohr}
106