xref: /plugin/struct/meta/AggregationFilter.php (revision f1812f0b7ac4d9c715e38beb78ffe9711588b0c0)
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        $schemas = $this->searchConfig->getSchemas();
24        $schema = $schemas[0]->getTable();
25
26        $colValues = $this->getAllColumnValues($this->result);
27
28        $form = new Form(['method' => 'get'], true);
29        $form->addClass('struct-filter-form search-results-form');
30        $form->setHiddenField('id', getID());
31
32        $form->addFieldsetOpen()->addClass('struct-filter-form search-form');
33        $form->addHTML('<legend>' . $this->helper->getLang('filter_title') . '</legend>');
34
35        $form->addTagOpen('div')
36            ->addClass('advancedOptions');
37
38        // column dropdowns
39        $num = 0;
40        foreach ($colValues as $colName => $colData) {
41            $qualifiedColName = $colName[0] !== '%' ? "$schema.$colName" : $colName;
42
43            $form->addTagOpen('div')
44                ->addClass('toggle')
45                ->id("__filter-$colName")
46                ->attr('aria-haspopup', 'true');
47
48            // popup toggler uses header if defined in syntax, otherwise label
49            $header = $colData['label'];
50            if (!empty($this->data['headers'][$num])) {
51                $header = $this->data['headers'][$num];
52            }
53            $form->addTagOpen('div')->addClass('current');
54            $form->addHTML($header);
55            $form->addTagClose('div');
56
57            $form->addTagOpen('ul')->attr('aria-expanded', 'false');
58
59            $i = 0;
60            foreach ($colData['values'] as $value) {
61                $form->addTagOpen('li');
62                $form->addRadioButton(SearchConfigParameters::$PARAM_FILTER . "[$qualifiedColName*~]")
63                    ->val($value)
64                    ->id("__$schema.$colName-" . $i);
65                $form->addLabel($value, "__$schema.$colName-" . $i)
66                    ->attr('title', $value);
67                $form->addTagClose('li');
68                $i++;
69            }
70
71            $form->addTagClose('ul');
72            $form->addTagClose('div'); // close div.toggle
73            $num++;
74        }
75
76        $form->addButton('struct-filter-submit', $this->helper->getLang('filter_button'))
77            ->attr('type', 'submit')
78            ->addClass('struct-filter-submit');
79
80        $form->addTagClose('div'); // close div.advancedOptions
81        $form->addFieldsetClose();
82
83        $this->renderer->doc .= $form->toHTML();
84    }
85
86    /**
87     * Get all values from given search result grouped by column
88     *
89     * @return array
90     */
91    protected function getAllColumnValues($result)
92    {
93        $colValues = [];
94
95        foreach ($result as $row) {
96            foreach ($row as $value) {
97                /** @var Value $value */
98                $colName = $value->getColumn()->getFullQualifiedLabel();
99                $colValues[$colName]['label'] = $value->getColumn()->getTranslatedLabel();
100                $colValues[$colName]['values'] = $colValues[$colName]['values'] ?? [];
101
102                $opt = $value->getDisplayValue();
103
104                if (empty($opt)) continue;
105
106                // handle multiple values
107                if (is_array($opt)) {
108                    $colValues[$colName]['values'] = array_merge($colValues[$colName]['values'], $opt);
109                } else {
110                    $colValues[$colName]['values'][] = $opt;
111                }
112            }
113        }
114
115        array_walk($colValues, function (&$col) {
116            $unique = array_unique($col['values']);
117            Sort::sort($unique);
118            $col['values'] = $unique;
119        });
120
121        return $colValues;
122    }
123}
124