1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
|
<?php
/**
* This class provides a generic search widget for the sidebar.
*
* @author Jan-Hendrik Willms <tleilax+studip@gmail.com>
* @since 3.1
* @license GPL2 or any later version
* @copyright Stud.IP Core Group
*/
class SearchWidget extends SidebarWidget
{
const INDEX = 'search';
protected $url;
protected $needles = [];
protected $filters = [];
protected $method = 'get';
protected $id = null;
protected $onsubmit = null;
protected ?string $onclear = null;
/**
* Constructor for the widget.
*
* @param String $url URL to send the search to
*/
public function __construct($url = '')
{
parent::__construct();
$this->url = $url ?: $_SERVER['REQUEST_URI'];
$this->title = _('Suche');
$this->template = 'sidebar/search-widget';
}
/**
* Sets the request method used for the form.
*/
public function setMethod($method)
{
$this->method = $method;
}
/**
* Returns the request method used for the form.
*
* @return string containing the chosen request method.
*/
public function getMethod()
{
return $this->method;
}
/**
* Add a needle to search (optionally as quick search)
*
* @param String $label Label for the input element
* @param String $name Name of the input (which will be the
* transmitted name attribute)
* @param bool $placeholder Use label as placeholder (this will hide
* the associated label)
* @param mixed $quick_search An optional SearchType object if quick
* search should be used
* @param mixed $js_func Optional name of a js function or a js
* function itself that's executed when an
* entry of the found elements is selected
* @param array $attributes An array with optional HTML attributes
* that shall be attached to the input element
* that is constructed when rendering
* this "needle".
* The array keys specify the attribute names
* while the array values specify the attribute
* values.
* Note that this parameter is ignored
* when a quick search object is provided!
*/
public function addNeedle($label, $name, $placeholder = false, SearchType $quick_search = null, $js_func = null, $value = null, array $attributes = [])
{
$value = $value ?: Request::get($name);
$this->needles[] = compact(['label', 'name', 'placeholder', 'value', 'quick_search', 'js_func', 'attributes']);
}
/**
* Add a filter option. This will create a checkbox with the given key
* as the name attribute.
*
* @param String $label Label of the filter
* @param String $key Key/name of the filter (this will be the name
* attribute)
*/
public function addFilter($label, $key)
{
$this->filters[$key] = $label;
}
/**
* Returns whether the widgets has any elements. Since this widget uses
* a special template, not all elements are "real" SidebarElements.
*
* @return bool If widget has any element.
*/
public function hasElements()
{
return count($this->elements) + count($this->needles) + count($this->filters) > 0;
}
public function setOnSubmitHandler($onsubmit)
{
$this->onsubmit = $onsubmit;
}
public function setOnClearHandler(string $onclear): void
{
$this->onclear = $onclear;
}
/**
* Renders the widget.
*
* @param Array $variables Unused variables parameter
* @return String containing the html output of the widget
*/
public function render($variables = [])
{
$query = parse_url($this->url, PHP_URL_QUERY);
if ($query) {
$this->url = str_replace('?' . $query, '', $this->url);
parse_str($query ?: '', $query_params);
} else {
$query_params = [];
}
$this->template_variables['url'] = $this->url;
$this->template_variables['url_params'] = $query_params;
$this->template_variables['method'] = $this->method;
foreach ($this->needles as $index => $needle) {
if ($needle['quick_search']) {
$quick_search = QuickSearch::get($needle['name'], $needle['quick_search']);
if ($needle['js_func'] !== null) {
$quick_search->fireJSFunctionOnSelect($needle['js_func']);
}
$needle['quick_search'] = $quick_search;
$this->needles[$index] = $needle;
}
}
$this->template_variables['reset_search'] = '';
if ($this->hasData()) {
// Remove needles from query params for reset link
$reset_params = $query_params;
foreach ($this->needles as $needle) {
unset($reset_params[$needle['name']]);
// Search view in Wiki must be cleared.
if (isset($reset_params['view']) && $reset_params['view'] === 'search') {
$reset_params['view'] = 'show';
}
// Search view in Forum must be cleared.
if (isset($reset_params['backend']) && $reset_params['backend'] === 'search') {
unset($reset_params['backend']);
$this->url = str_replace('index/search', 'index', $this->url);
}
}
$reset_link = URLHelper::getLink($this->url, array_merge($reset_params, ['reset-search' => 1]));
$this->template_variables['reset_link'] = $reset_link;
} else {
$this->template_variables['reset_link'] = false;
}
$this->template_variables['needles'] = $this->needles;
$this->template_variables['filters'] = $this->filters;
$this->template_variables['has_data'] = $this->hasData();
$this->template_variables['onsubmit'] = $this->onsubmit;
$this->template_variables['onclear'] = $this->onclear;
return parent::render($variables);
}
/**
* Returns whether the widget has any data.
* The widget has data if it was submitted and any of the needles
* or needles has been filled out.
*
* @return bool indicating whether the request method matches and any
* element has data.
*/
protected function hasData()
{
if (Request::method() !== mb_strtoupper($this->method)) {
return false;
}
foreach ($this->needles as $needle) {
if ($needle['value']) {
return true;
}
}
foreach (array_keys($this->filters) as $key) {
if (Request::submitted($key) && !Request::int($key)) {
return true;
}
}
return false;
}
}
|