]> git.donarmstrong.com Git - roundcube.git/blob - program/steps/addressbook/search.inc
Imported Upstream version 0.7
[roundcube.git] / program / steps / addressbook / search.inc
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  | Licensed under the GNU GPL                                            |
11  |                                                                       |
12  | PURPOSE:                                                              |
13  |   Search action (and form) for address book contacts                  |
14  |                                                                       |
15  +-----------------------------------------------------------------------+
16  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
17  | Author: Aleksander Machniak <machniak@kolabsys.com>                   |
18  +-----------------------------------------------------------------------+
19
20  $Id: search.inc 456 2007-01-10 12:34:33Z thomasb $
21
22 */
23
24 if ($RCMAIL->action == 'search-create') {
25     $id   = get_input_value('_search', RCUBE_INPUT_POST);
26     $name = get_input_value('_name', RCUBE_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', Q($name), Q($result));
50     }
51     else
52         $OUTPUT->show_message($plugin['message'] ? $plugin['message'] : 'savedsearchcreateerror', 'error');
53
54     $OUTPUT->send();
55 }
56
57 if ($RCMAIL->action == 'search-delete') {
58     $id = get_input_value('_sid', RCUBE_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', Q($id));
70         // contact list will be cleared, clear also page counter
71         $OUTPUT->command('set_rowcount', rcube_label('nocontactsfound'));
72         $OUTPUT->set_env('pagecount', 0);
73     }
74     else
75         $OUTPUT->show_message($plugin['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, $CONFIG, $SEARCH_MODS_DEFAULT;
92
93     $adv = isset($_POST['_adv']);
94     $sid = get_input_value('_sid', RCUBE_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(get_input_value($key, RCUBE_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(get_input_value('_q', RCUBE_INPUT_GET, true));
119         $fields = explode(',', get_input_value('_headers', RCUBE_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
143     // get sources list
144     $sources    = $RCMAIL->get_address_sources();
145     $search_set = array();
146     $records    = array();
147
148     foreach ($sources as $s) {
149         $source = $RCMAIL->get_address_book($s['id']);
150
151         // check if search fields are supported....
152         if (is_array($fields)) {
153             $cols = $source->coltypes[0] ? array_flip($source->coltypes) : $source->coltypes;
154             $supported = 0;
155
156             foreach ($fields as $f) {
157                 if (array_key_exists($f, $cols)) {
158                     $supported ++;
159                 }
160             }
161
162             // in advanced search we require all fields (AND operator)
163             // in quick search we require at least one field (OR operator)
164             if (($adv && $supported < count($fields)) || (!$adv && !$supported)) {
165                 continue;
166             }
167         }
168
169         // reset page
170         $source->set_page(1);
171         $source->set_pagesize(9999);
172
173         // get contacts count
174         $result = $source->search($fields, $search, $mode, false);
175
176         if (!$result->count) {
177             continue;
178         }
179
180         // get records
181         $result = $source->list_records(array('name', 'email'));
182
183         while ($row = $result->next()) {
184             $row['sourceid'] = $s['id'];
185             $key = $row['name'] . ':' . $row['sourceid'];
186             $records[$key] = $row;
187         }
188
189         unset($result);
190         $search_set[$s['id']] = $source->get_search_set();
191     }
192
193     // sort the records
194     ksort($records, SORT_LOCALE_STRING);
195
196     // create resultset object
197     $count  = count($records);
198     $result = new rcube_result_set($count);
199
200     // cut first-page records
201     if ($CONFIG['pagesize'] < $count) {
202         $records = array_slice($records, 0, $CONFIG['pagesize']);
203     }
204
205     $result->records = array_values($records);
206
207     // search request ID
208     $search_request = md5('addr'
209         .(is_array($fields) ? implode($fields, ',') : $fields)
210         .(is_array($search) ? implode($search, ',') : $search));
211
212     // save search settings in session
213     $_SESSION['search'][$search_request] = $search_set;
214     $_SESSION['search_params'] = array('id' => $search_request, 'data' => array($fields, $search));
215     $_SESSION['page'] = 1;
216
217     if ($adv)
218         $OUTPUT->command('list_contacts_clear');
219
220     if ($result->count > 0) {
221         // create javascript list
222         rcmail_js_contacts_list($result);
223         $OUTPUT->show_message('contactsearchsuccessful', 'confirmation', array('nr' => $result->count));
224     }
225     else {
226         $OUTPUT->show_message('nocontactsfound', 'notice');
227     }
228
229     // update message count display
230     $OUTPUT->command('set_env', 'search_request', $search_request);
231     $OUTPUT->command('set_env', 'pagecount', ceil($result->count / $CONFIG['pagesize']));
232     $OUTPUT->command('set_rowcount', rcmail_get_rowcount_text($result));
233     // Re-set current source
234     $OUTPUT->command('set_env', 'search_id', $sid);
235     $OUTPUT->command('set_env', 'source', '');
236     $OUTPUT->command('set_env', 'group', '');
237
238     // unselect currently selected directory/group
239     if (!$sid)
240         $OUTPUT->command('unselect_directory');
241     $OUTPUT->command('update_group_commands');
242
243     // send response
244     $OUTPUT->send($adv ? 'iframe' : null);
245 }
246
247 function rcmail_contact_search_form($attrib)
248 {
249     global $RCMAIL, $CONTACT_COLTYPES;
250
251     $i_size = !empty($attrib['size']) ? $attrib['size'] : 30;
252
253     $form = array(
254         'main' => array(
255             'name'    => rcube_label('contactproperties'),
256             'content' => array(
257             ),
258         ),
259         'personal' => array(
260             'name'    => rcube_label('personalinfo'),
261             'content' => array(
262             ),
263         ),
264         'other' => array(
265             'name'    => rcube_label('other'),
266             'content' => array(
267             ),
268         ),
269     );
270
271     // get supported coltypes from all address sources
272     $sources  = $RCMAIL->get_address_sources();
273     $coltypes = array();
274
275     foreach ($sources as $s) {
276         $CONTACTS = $RCMAIL->get_address_book($s['id']);
277
278         if (is_array($CONTACTS->coltypes)) {
279             $contact_cols = $CONTACTS->coltypes[0] ? array_flip($CONTACTS->coltypes) : $CONTACTS->coltypes;
280             $coltypes = array_merge($coltypes, $contact_cols);
281         }
282     }
283
284     // merge supported coltypes with $CONTACT_COLTYPES
285     foreach ($coltypes as $col => $colprop) {
286         $coltypes[$col] = $CONTACT_COLTYPES[$col] ? array_merge($CONTACT_COLTYPES[$col], (array)$colprop) : (array)$colprop;
287     }
288
289     // build form fields list
290     foreach ($coltypes as $col => $colprop)
291     {
292         if ($colprop['type'] != 'image' && !$colprop['nosearch'])
293         {
294             $ftype    = $colprop['type'] == 'select' ? 'select' : 'text';
295             $label    = isset($colprop['label']) ? $colprop['label'] : rcube_label($col);
296             $category = $colprop['category'] ? $colprop['category'] : 'other';
297
298             if ($ftype == 'text')
299                 $colprop['size'] = $i_size;
300
301             $content  = html::div('row', html::div('contactfieldlabel label', Q($label))
302                 . html::div('contactfieldcontent', rcmail_get_edit_field('search_'.$col, '', $colprop, $ftype)));
303
304             $form[$category]['content'][] = $content;
305         }
306     }
307
308     $hiddenfields = new html_hiddenfield();
309     $hiddenfields->add(array('name' => '_adv', 'value' => 1));
310
311     $out = $RCMAIL->output->request_form(array(
312         'name' => 'form', 'method' => 'post',
313         'task' => $RCMAIL->task, 'action' => 'search',
314         'noclose' => true) + $attrib, $hiddenfields->show());
315
316     $RCMAIL->output->add_gui_object('editform', $attrib['id']);
317
318     unset($attrib['name']);
319     unset($attrib['id']);
320
321     foreach ($form as $f) {
322         if (!empty($f['content'])) {
323             $content = html::div('contactfieldgroup', join("\n", $f['content']));
324
325             $out .= html::tag('fieldset', $attrib,
326                 html::tag('legend', null, Q($f['name']))
327                 . $content) . "\n";
328         }
329     }
330
331     return $out . '</form>';
332 }