1<?php
2/**
3 * DokuWiki Plugin elasticsearch (Form Helper Component)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  Andreas Gohr <gohr@cosmocode.de>
7 * @author  Anna Dabrowska <dabrowska@cosmocode.de>
8 */
9
10use dokuwiki\Form\Form;
11
12/**
13 * Search form helper
14 */
15class helper_plugin_elasticsearch_form extends DokuWiki_Plugin
16{
17    /**
18     * Replacement for the standard search form
19     *
20     * @param array $aggregations
21     */
22    public function tpl($aggregations)
23    {
24        global $lang;
25        global $QUERY;
26
27        $searchForm = (new Form(['method' => 'get'], true))->addClass('search-results-form');
28        $searchForm->setHiddenField('do', 'search');
29
30        $searchForm->addFieldsetOpen()->addClass('search-form');
31        $searchForm->addTextInput('q')->val($QUERY)->useInput(false);
32        $searchForm->addButton('', $lang['btn_search'])->attr('type', 'submit');
33
34        $this->addAdvancedSearch($searchForm, $aggregations);
35
36        $searchForm->addFieldsetClose();
37
38        echo $searchForm->toHTML();
39    }
40
41    /**
42     * Advanced search
43     *
44     * @param Form $searchForm
45     * @param array $aggregations
46     */
47    protected function addAdvancedSearch(Form $searchForm, array $aggregations)
48    {
49        $searchForm->addTagOpen('div')
50            ->addClass('advancedOptions')
51            ->attr('style', 'display: none;')
52            ->attr('aria-hidden', 'true');
53
54        foreach ($aggregations as $term => $aggregation) {
55            // keep canonical 'ns' search parameter for namespaces
56            $param = $term === 'namespace' ? 'ns' : $term;
57            $this->addCheckboxSelector($searchForm, $aggregation['buckets'], $param);
58        }
59        $this->addDateSelector($searchForm);
60        $this->addLanguageSelector($searchForm);
61        $searchForm->addTagClose('div');
62    }
63
64    /**
65     * Filter with checkboxes
66     *
67     * @param Form $searchForm
68     * @param array $aggregations Namespace aggregations
69     * @param string $param Prefix to use in input names
70     */
71    protected function addCheckboxSelector(Form $searchForm, array $aggregations, $param)
72    {
73        if (!empty($aggregations)) {
74            $pluginSearchConfigs = \action_plugin_elasticsearch_search::getRawPluginSearchConfigs();
75            $selectorId = !empty($pluginSearchConfigs[$param]['id']) ? $pluginSearchConfigs[$param]['id'] : 'plugin__elasticsearch-' . $param;
76
77            $searchForm->addTagOpen('div')
78                ->addClass('toggle')
79                ->id($selectorId)
80                ->attr('aria-haspopup', 'true');
81
82            // popup toggler
83            $searchForm->addTagOpen('div')->addClass('current');
84            $label = $param === 'ns' ? $this->getLang('nsp') : $pluginSearchConfigs[$param]['label'];
85            $searchForm->addHTML($label);
86            $searchForm->addTagClose('div');
87
88            // options
89            $i = 0;
90            $searchForm->addTagOpen('ul')->attr('aria-expanded', 'false');
91            foreach ($aggregations as $agg) {
92                $searchForm->addTagOpen('li');
93                $searchForm->addCheckbox($param . '[]')->val($agg['key'])->id("__$param-" . $i);
94                $searchForm->addLabel(shorten('', $agg['key'], 25) . ' (' . $agg['doc_count'] . ')', "__$param-" . $i)
95                    ->attr('title', $agg['key']);
96                $searchForm->addTagClose('li');
97                $i++;
98            }
99            $searchForm->addTagClose('ul');
100
101            $searchForm->addTagClose('div');
102        }
103    }
104
105    /**
106     * Date range filter
107     *
108     * @param Form $searchForm
109     */
110    protected function addDateSelector(Form $searchForm)
111    {
112        global $lang;
113
114        $options = [
115            'any' => $lang['search_any_time'],
116            'week' =>  $lang['search_past_7_days'],
117            'month' => $lang['search_past_month'],
118            'year' => $lang['search_past_year'],
119        ];
120
121        $searchForm->addTagOpen('div')->addClass('toggle')->attr('aria-haspopup', 'true');
122
123        // popup toggler
124        $searchForm->addTagOpen('div')->addClass('current');
125        $searchForm->addHTML($this->getLang('lastmod'));
126        $searchForm->addTagClose('div');
127
128        // options
129        $i = 0;
130        $searchForm->addTagOpen('ul')->attr('aria-expanded', 'false');
131        foreach ($options as $opt => $label) {
132            $searchForm->addTagOpen('li');
133            $searchForm->addRadioButton('min')->val($opt)->id('__min-' . $i);
134            $searchForm->addLabel($label, '__min-' . $i);
135            $searchForm->addTagClose('li');
136            $i++;
137        }
138        $searchForm->addTagClose('ul');
139
140        $searchForm->addTagClose('div');
141    }
142
143    /**
144     * Language filter based on the translation plugin
145     *
146     * @param Form $searchForm
147     */
148    protected function addLanguageSelector(Form $searchForm)
149    {
150        /** @var helper_plugin_translation $transplugin */
151        $transplugin = plugin_load('helper', 'translation');
152        if (!$transplugin) return;
153
154        $translations = $transplugin->translations;
155        if (empty($translations)) return;
156
157        $searchForm->addTagOpen('div')
158            ->addClass('toggle')
159            ->id('plugin__elasticsearch-lang')
160            ->attr('aria-haspopup', 'true');
161
162        // popup toggler
163        $searchForm->addTagOpen('div')->addClass('current');
164        $label = $this->getLang('lang');
165        $searchForm->addHTML($label);
166        $searchForm->addTagClose('div');
167
168        // options
169        $i = 0;
170        $searchForm->addTagOpen('ul')->attr('aria-expanded', 'false');
171        foreach ($translations as $lang) {
172            $searchForm->addTagOpen('li');
173            $searchForm->addCheckbox('lang[]')->val($lang)->id("__lang-" . $i);
174            $searchForm->addLabel($lang, "__lang-" . $i)
175                ->attr('title', $lang);
176            $searchForm->addTagClose('li');
177            $i++;
178        }
179        $searchForm->addTagClose('ul');
180        $searchForm->addTagClose('div');
181    }
182}
183