0
|
1 <?php
|
|
2
|
|
3 /**
|
|
4 +-----------------------------------------------------------------------+
|
|
5 | program/steps/addressbook/search.inc |
|
|
6 | |
|
|
7 | This file is part of the Roundcube Webmail client |
|
|
8 | Copyright (C) 2005-2011, The Roundcube Dev Team |
|
|
9 | Copyright (C) 2011, Kolab Systems AG |
|
|
10 | |
|
|
11 | Licensed under the GNU General Public License version 3 or |
|
|
12 | any later version with exceptions for skins & plugins. |
|
|
13 | See the README file for a full license statement. |
|
|
14 | |
|
|
15 | PURPOSE: |
|
|
16 | Search action (and form) for address book contacts |
|
|
17 | |
|
|
18 +-----------------------------------------------------------------------+
|
|
19 | Author: Thomas Bruederli <roundcube@gmail.com> |
|
|
20 | Author: Aleksander Machniak <machniak@kolabsys.com> |
|
|
21 +-----------------------------------------------------------------------+
|
|
22 */
|
|
23
|
|
24 if ($RCMAIL->action == 'search-create') {
|
|
25 $id = rcube_utils::get_input_value('_search', rcube_utils::INPUT_POST);
|
|
26 $name = rcube_utils::get_input_value('_name', rcube_utils::INPUT_POST, true);
|
|
27
|
|
28 if (($params = $_SESSION['search_params']) && $params['id'] == $id) {
|
|
29
|
|
30 $data = array(
|
|
31 'type' => rcube_user::SEARCH_ADDRESSBOOK,
|
|
32 'name' => $name,
|
|
33 'data' => array(
|
|
34 'fields' => $params['data'][0],
|
|
35 'search' => $params['data'][1],
|
|
36 ),
|
|
37 );
|
|
38
|
|
39 $plugin = $RCMAIL->plugins->exec_hook('saved_search_create', array('data' => $data));
|
|
40
|
|
41 if (!$plugin['abort'])
|
|
42 $result = $RCMAIL->user->insert_search($plugin['data']);
|
|
43 else
|
|
44 $result = $plugin['result'];
|
|
45 }
|
|
46
|
|
47 if ($result) {
|
|
48 $OUTPUT->show_message('savedsearchcreated', 'confirmation');
|
|
49 $OUTPUT->command('insert_saved_search', rcube::Q($name), rcube::Q($result));
|
|
50 }
|
|
51 else
|
|
52 $OUTPUT->show_message($plugin['message'] ?: 'savedsearchcreateerror', 'error');
|
|
53
|
|
54 $OUTPUT->send();
|
|
55 }
|
|
56
|
|
57 if ($RCMAIL->action == 'search-delete') {
|
|
58 $id = rcube_utils::get_input_value('_sid', rcube_utils::INPUT_POST);
|
|
59
|
|
60 $plugin = $RCMAIL->plugins->exec_hook('saved_search_delete', array('id' => $id));
|
|
61
|
|
62 if (!$plugin['abort'])
|
|
63 $result = $RCMAIL->user->delete_search($id);
|
|
64 else
|
|
65 $result = $plugin['result'];
|
|
66
|
|
67 if ($result) {
|
|
68 $OUTPUT->show_message('savedsearchdeleted', 'confirmation');
|
|
69 $OUTPUT->command('remove_search_item', rcube::Q($id));
|
|
70 // contact list will be cleared, clear also page counter
|
|
71 $OUTPUT->command('set_rowcount', $RCMAIL->gettext('nocontactsfound'));
|
|
72 $OUTPUT->set_env('pagecount', 0);
|
|
73 }
|
|
74 else
|
|
75 $OUTPUT->show_message($plugin['message'] ?: 'savedsearchdeleteerror', 'error');
|
|
76
|
|
77 $OUTPUT->send();
|
|
78 }
|
|
79
|
|
80
|
|
81 if (!isset($_GET['_form'])) {
|
|
82 rcmail_contact_search();
|
|
83 }
|
|
84
|
|
85 $OUTPUT->add_handler('searchform', 'rcmail_contact_search_form');
|
|
86 $OUTPUT->send('contactsearch');
|
|
87
|
|
88
|
|
89 function rcmail_contact_search()
|
|
90 {
|
|
91 global $RCMAIL, $OUTPUT, $SEARCH_MODS_DEFAULT, $PAGE_SIZE;
|
|
92
|
|
93 $adv = isset($_POST['_adv']);
|
|
94 $sid = rcube_utils::get_input_value('_sid', rcube_utils::INPUT_GET);
|
|
95
|
|
96 // get search criteria from saved search
|
|
97 if ($sid && ($search = $RCMAIL->user->get_search($sid))) {
|
|
98 $fields = $search['data']['fields'];
|
|
99 $search = $search['data']['search'];
|
|
100 }
|
|
101 // get fields/values from advanced search form
|
|
102 else if ($adv) {
|
|
103 foreach (array_keys($_POST) as $key) {
|
|
104 $s = trim(rcube_utils::get_input_value($key, rcube_utils::INPUT_POST, true));
|
|
105 if (strlen($s) && preg_match('/^_search_([a-zA-Z0-9_-]+)$/', $key, $m)) {
|
|
106 $search[] = $s;
|
|
107 $fields[] = $m[1];
|
|
108 }
|
|
109 }
|
|
110
|
|
111 if (empty($fields)) {
|
|
112 // do nothing, show the form again
|
|
113 return;
|
|
114 }
|
|
115 }
|
|
116 // quick-search
|
|
117 else {
|
|
118 $search = trim(rcube_utils::get_input_value('_q', rcube_utils::INPUT_GET, true));
|
|
119 $fields = explode(',', rcube_utils::get_input_value('_headers', rcube_utils::INPUT_GET));
|
|
120
|
|
121 if (empty($fields)) {
|
|
122 $fields = array_keys($SEARCH_MODS_DEFAULT);
|
|
123 }
|
|
124 else {
|
|
125 $fields = array_filter($fields);
|
|
126 }
|
|
127
|
|
128 // update search_mods setting
|
|
129 $old_mods = $RCMAIL->config->get('addressbook_search_mods');
|
|
130 $search_mods = array_fill_keys($fields, 1);
|
|
131 if ($old_mods != $search_mods) {
|
|
132 $RCMAIL->user->save_prefs(array('addressbook_search_mods' => $search_mods));
|
|
133 }
|
|
134
|
|
135 if (in_array('*', $fields)) {
|
|
136 $fields = '*';
|
|
137 }
|
|
138 }
|
|
139
|
|
140 // Values matching mode
|
|
141 $mode = (int) $RCMAIL->config->get('addressbook_search_mode');
|
|
142 $mode |= rcube_addressbook::SEARCH_GROUPS;
|
|
143
|
|
144 // get sources list
|
|
145 $sources = $RCMAIL->get_address_sources();
|
|
146 $search_set = array();
|
|
147 $records = array();
|
|
148 $sort_col = $RCMAIL->config->get('addressbook_sort_col', 'name');
|
|
149 $afields = $RCMAIL->config->get('contactlist_fields');
|
|
150
|
|
151 foreach ($sources as $s) {
|
|
152 $source = $RCMAIL->get_address_book($s['id']);
|
|
153
|
|
154 // check if search fields are supported....
|
|
155 if (is_array($fields)) {
|
|
156 $cols = $source->coltypes[0] ? array_flip($source->coltypes) : $source->coltypes;
|
|
157 $supported = 0;
|
|
158
|
|
159 foreach ($fields as $f) {
|
|
160 if (array_key_exists($f, $cols)) {
|
|
161 $supported ++;
|
|
162 }
|
|
163 }
|
|
164
|
|
165 // in advanced search we require all fields (AND operator)
|
|
166 // in quick search we require at least one field (OR operator)
|
|
167 if (($adv && $supported < count($fields)) || (!$adv && !$supported)) {
|
|
168 continue;
|
|
169 }
|
|
170 }
|
|
171
|
|
172 // reset page
|
|
173 $source->set_page(1);
|
|
174 $source->set_pagesize(9999);
|
|
175
|
|
176 // get contacts count
|
|
177 $result = $source->search($fields, $search, $mode, false);
|
|
178
|
|
179 if (!$result->count) {
|
|
180 continue;
|
|
181 }
|
|
182
|
|
183 // get records
|
|
184 $result = $source->list_records($afields);
|
|
185
|
|
186 while ($row = $result->next()) {
|
|
187 $row['sourceid'] = $s['id'];
|
|
188 $key = rcube_addressbook::compose_contact_key($row, $sort_col);
|
|
189 $records[$key] = $row;
|
|
190 }
|
|
191
|
|
192 unset($result);
|
|
193 $search_set[$s['id']] = $source->get_search_set();
|
|
194 }
|
|
195
|
|
196 // sort the records
|
|
197 ksort($records, SORT_LOCALE_STRING);
|
|
198
|
|
199 // create resultset object
|
|
200 $count = count($records);
|
|
201 $result = new rcube_result_set($count);
|
|
202
|
|
203 // cut first-page records
|
|
204 if ($PAGE_SIZE < $count) {
|
|
205 $records = array_slice($records, 0, $PAGE_SIZE);
|
|
206 }
|
|
207
|
|
208 $result->records = array_values($records);
|
|
209
|
|
210 // search request ID
|
|
211 $search_request = md5('addr'
|
|
212 .(is_array($fields) ? implode($fields, ',') : $fields)
|
|
213 .(is_array($search) ? implode($search, ',') : $search));
|
|
214
|
|
215 // save search settings in session
|
|
216 $_SESSION['search'][$search_request] = $search_set;
|
|
217 $_SESSION['search_params'] = array('id' => $search_request, 'data' => array($fields, $search));
|
|
218 $_SESSION['page'] = 1;
|
|
219
|
|
220 if ($adv)
|
|
221 $OUTPUT->command('list_contacts_clear');
|
|
222
|
|
223 if ($result->count > 0) {
|
|
224 // create javascript list
|
|
225 rcmail_js_contacts_list($result);
|
|
226 $OUTPUT->show_message('contactsearchsuccessful', 'confirmation', array('nr' => $result->count));
|
|
227 }
|
|
228 else {
|
|
229 $OUTPUT->show_message('nocontactsfound', 'notice');
|
|
230 }
|
|
231
|
|
232 // update message count display
|
|
233 $OUTPUT->set_env('search_request', $search_request);
|
|
234 $OUTPUT->set_env('pagecount', ceil($result->count / $PAGE_SIZE));
|
|
235 $OUTPUT->command('set_rowcount', rcmail_get_rowcount_text($result));
|
|
236 // Re-set current source
|
|
237 $OUTPUT->set_env('search_id', $sid);
|
|
238 $OUTPUT->set_env('source', '');
|
|
239 $OUTPUT->set_env('group', '');
|
|
240 // Re-set list header
|
|
241 $OUTPUT->command('set_group_prop', null);
|
|
242
|
|
243 if ($adv) {
|
|
244 $OUTPUT->command('parent.set_env', array(
|
|
245 'search_request' => $search_request,
|
|
246 'pagecount' => ceil($result->count / $PAGE_SIZE),
|
|
247 'search_id' => $sid,
|
|
248 'source' => '',
|
|
249 'group' => '',
|
|
250 ));
|
|
251 }
|
|
252
|
|
253 if (!$sid) {
|
|
254 // unselect currently selected directory/group
|
|
255 $OUTPUT->command('unselect_directory');
|
|
256 // enable "Save search" command
|
|
257 $OUTPUT->command('enable_command', 'search-create', true);
|
|
258 }
|
|
259 $OUTPUT->command('update_group_commands');
|
|
260
|
|
261 // send response
|
|
262 $OUTPUT->send($adv ? 'iframe' : null);
|
|
263 }
|
|
264
|
|
265 function rcmail_contact_search_form($attrib)
|
|
266 {
|
|
267 global $RCMAIL, $CONTACT_COLTYPES;
|
|
268
|
|
269 $i_size = $attrib['size'] ?: 30;
|
|
270
|
|
271 $form = array(
|
|
272 'main' => array(
|
|
273 'name' => $RCMAIL->gettext('properties'),
|
|
274 'content' => array(
|
|
275 ),
|
|
276 ),
|
|
277 'personal' => array(
|
|
278 'name' => $RCMAIL->gettext('personalinfo'),
|
|
279 'content' => array(
|
|
280 ),
|
|
281 ),
|
|
282 'other' => array(
|
|
283 'name' => $RCMAIL->gettext('other'),
|
|
284 'content' => array(
|
|
285 ),
|
|
286 ),
|
|
287 );
|
|
288
|
|
289 // get supported coltypes from all address sources
|
|
290 $sources = $RCMAIL->get_address_sources();
|
|
291 $coltypes = array();
|
|
292
|
|
293 foreach ($sources as $s) {
|
|
294 $CONTACTS = $RCMAIL->get_address_book($s['id']);
|
|
295
|
|
296 if (is_array($CONTACTS->coltypes)) {
|
|
297 $contact_cols = $CONTACTS->coltypes[0] ? array_flip($CONTACTS->coltypes) : $CONTACTS->coltypes;
|
|
298 $coltypes = array_merge($coltypes, $contact_cols);
|
|
299 }
|
|
300 }
|
|
301
|
|
302 // merge supported coltypes with $CONTACT_COLTYPES
|
|
303 foreach ($coltypes as $col => $colprop) {
|
|
304 $coltypes[$col] = $CONTACT_COLTYPES[$col] ? array_merge($CONTACT_COLTYPES[$col], (array)$colprop) : (array)$colprop;
|
|
305 }
|
|
306
|
|
307 // build form fields list
|
|
308 foreach ($coltypes as $col => $colprop)
|
|
309 {
|
|
310 if ($colprop['type'] != 'image' && !$colprop['nosearch'])
|
|
311 {
|
|
312 $ftype = $colprop['type'] == 'select' ? 'select' : 'text';
|
|
313 $label = isset($colprop['label']) ? $colprop['label'] : $RCMAIL->gettext($col);
|
|
314 $category = $colprop['category'] ?: 'other';
|
|
315
|
|
316 // load jquery UI datepicker for date fields
|
|
317 if ($colprop['type'] == 'date')
|
|
318 $colprop['class'] .= ($colprop['class'] ? ' ' : '') . 'datepicker';
|
|
319 else if ($ftype == 'text')
|
|
320 $colprop['size'] = $i_size;
|
|
321
|
|
322
|
|
323 $content = html::div('row', html::div('contactfieldlabel label', rcube::Q($label))
|
|
324 . html::div('contactfieldcontent', rcube_output::get_edit_field('search_'.$col, '', $colprop, $ftype)));
|
|
325
|
|
326 $form[$category]['content'][] = $content;
|
|
327 }
|
|
328 }
|
|
329
|
|
330 $hiddenfields = new html_hiddenfield();
|
|
331 $hiddenfields->add(array('name' => '_adv', 'value' => 1));
|
|
332
|
|
333 $out = $RCMAIL->output->request_form(array(
|
|
334 'name' => 'form', 'method' => 'post',
|
|
335 'task' => $RCMAIL->task, 'action' => 'search',
|
|
336 'noclose' => true) + $attrib, $hiddenfields->show());
|
|
337
|
|
338 $RCMAIL->output->add_gui_object('editform', $attrib['id']);
|
|
339
|
|
340 unset($attrib['name']);
|
|
341 unset($attrib['id']);
|
|
342
|
|
343 foreach ($form as $f) {
|
|
344 if (!empty($f['content'])) {
|
|
345 $content = html::div('contactfieldgroup', join("\n", $f['content']));
|
|
346
|
|
347 $out .= html::tag('fieldset', $attrib,
|
|
348 html::tag('legend', null, rcube::Q($f['name']))
|
|
349 . $content) . "\n";
|
|
350 }
|
|
351 }
|
|
352
|
|
353 return $out . '</form>';
|
|
354 }
|