/[drupal]/contributions/modules/sphinx/sphinx.module
ViewVC logotype

Contents of /contributions/modules/sphinx/sphinx.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.3 - (show annotations) (download) (as text)
Thu Sep 25 13:13:19 2008 UTC (14 months ago) by johsw
Branch: MAIN
CVS Tags: HEAD
Branch point for: DRUPAL-6--1
Changes since 1.2: +52 -21 lines
File MIME type: text/x-php
Inclusion of facet functionality
1 <?php
2 // $Id$
3
4
5 /**
6 * @file
7 * Sphinx module
8 *
9 * This module interfaces Sphinxsearch with Drupal (http://www.sphinxsearch.com)
10 *
11 * The module is made by Johs. Wehner (http://drupal.org/user/58666)
12 * The module is sponsored by Dagbladet Information (http://www.information.dk)
13 */
14
15
16 $path = './'. drupal_get_path('module', 'sphinx') .'/includes/api';
17 $api_file = $path .'/sphinxapi.php';
18 if (file_exists($api_file)) {
19 include_once($api_file);
20 }
21 require ('./'. drupal_get_path('module', 'sphinx') .'/sphinx_admin.inc.php');
22
23 /**
24 * Implementation of hook_menu().
25 */
26 function sphinx_menu() {
27 if (!$may_cache) {
28 $items[] = array(
29 'path' => 'admin/settings/sphinx',
30 'title' => t('Sphinx settings'),
31 'description' => t('Configure the Sphinx search and result pages'),
32 'callback' => '_sphinx_admin',
33 'access' => user_access('administer sphinx search'),
34 'type' => MENU_NORMAL_ITEM,
35 );
36 $items[] = array(
37 'path' => 'admin/settings/sphinx/main',
38 'title' => t('Sphinx settings'),
39 'description' => t('Configure the Sphinx search and result pages'),
40 'callback' => '_sphinx_admin',
41 'access' => user_access('administer sphinx search'),
42 'weight' => -1,
43 'type' => MENU_DEFAULT_LOCAL_TASK,
44 );
45
46 $items[] = array(
47 'path' => 'admin/settings/sphinx/indexes',
48 'title' => t('Indexes'),
49 'description' => t('Configure the Sphinx indexes'),
50 'callback' => '_sphinx_admin_indexes',
51 'access' => user_access('administer sphinx search'),
52 'type' => MENU_LOCAL_TASK,
53 );
54 $items[] = array(
55 'path' => 'admin/settings/sphinx/fields',
56 'title' => t('Fields'),
57 'description' => t('Configure the Sphinx fields'),
58 'callback' => '_sphinx_alter_fields',
59 'access' => user_access('administer sphinx search'),
60 'type' => MENU_CALLBACK,
61 );
62 $items[] = array(
63 'path' => 'admin/settings/sphinx/attributes',
64 'title' => t('Attributes'),
65 'description' => t('Configure the Sphinx attributes'),
66 'callback' => '_sphinx_alter_attributes',
67 'access' => user_access('administer sphinx search'),
68 'type' => MENU_CALLBACK,
69 );
70
71 $default = _sphinx_get_path_by_iid(variable_get('sphinx_default_index', ''));
72 if(!empty($default)) {
73 $items[] = array(
74 'path' => 'search',
75 'title' => utf8_encode('Search'),
76 'description' => t('Search'),
77 'callback' => 'drupal_goto',
78 'callback arguments' => array('search/'.$default),
79 'access' => user_access('use sphinx search'),
80 'type' => MENU_NORMAL_ITEM,
81 );
82 }
83 $res = db_query('SELECT iid, display_name, path FROM {sphinx_indexes} WHERE active=1');
84 while ($indexes = db_fetch_object($res)) {
85 $items[] = array(
86 'path' => 'search/'. $indexes->path,
87 'title' => t('Search !index', array('!index' => $indexes->display_name)),
88 'description' => t('Search !index', array('!index' => $indexes->display_name)),
89 'callback' => '_sphinx_search_page',
90 'callback arguments' => array(arg(1), arg(2)),
91 'access' => user_access('use index '. $indexes->display_name .'('. $indexes->iid .')'),
92 'type' => MENU_LOCAL_TASK,
93 );
94 }
95 }
96 return $items;
97 }
98
99 /**
100 * Implementation of hook_perm().
101 */
102 function sphinx_perm() {
103 $permissions = array('use sphinx search', 'administer sphinx search');
104 $res = db_query('SELECT iid, display_name, path FROM {sphinx_indexes} WHERE active=1');
105 while ($indexes = db_fetch_object($res)) {
106 $permissions[] = 'use index '. $indexes->display_name .'('. $indexes->iid .')';
107 }
108 return $permissions;
109 }
110
111 /**
112 * Implementation of hook_help().
113 */
114 function sphinx_help($section = '') {
115 $output = '';
116 switch ($section) {
117 case 'admin/help#infsphinxphpsearch':
118 $output = '<p>'. t('Sphinx search (Dagbladet Information)') .'</p>';
119 break;
120 }
121 return $output;
122 }
123
124 function _sphinx_get_index_by_path($path = null) {
125 if (!empty($path)) {
126 $res = db_query('SELECT iid FROM {sphinx_indexes} WHERE path="%s"', $path);
127 $index = db_fetch_object($res);
128 return $index->iid;
129 }
130 }
131
132 function _sphinx_get_index_by_name($path = null) {
133 if (!empty($path)) {
134 $res = db_query('SELECT iid FROM {sphinx_indexes} WHERE index_name="%s"', $path);
135 $index = db_fetch_object($res);
136 return $index->iid;
137 }
138 }
139
140 function _sphinx_get_path_by_iid($iid = null) {
141 if (!empty($iid)) {
142 $res = db_query('SELECT path FROM {sphinx_indexes} WHERE iid=%d', $iid);
143 $index = db_fetch_object($res);
144 return $index->path;
145 }
146 }
147
148 function _sphinx_get_attr_by_aid($aid = null) {
149 if (!empty($aid)) {
150 $res = db_query('SELECT attribute_name FROM {sphinx_attributes} WHERE aid=%d', $aid);
151 $index = db_fetch_object($res);
152 return $index->attribute_name;
153 }
154 }
155
156 function _sphinx_get_active_fields_by_iid($iid = null) {
157 if (!empty($iid)) {
158 $output = array();
159 $res = db_query('SELECT fid, field_name FROM {sphinx_fields} WHERE iid=%d && active=1', $iid);
160 while ($fields = db_fetch_object($res)) {
161 $output[$fields->fid] = $fields->field_name;
162 }
163 return $output;
164 }
165 }
166
167 /**
168 * The search page callback
169 */
170 function _sphinx_search_page($index_name, $needle = null) {
171
172 drupal_add_css(drupal_get_path('module', 'sphinx') .'/sphinx.css');
173 $iid = _sphinx_get_index_by_path($index_name);
174 $output = drupal_get_form('sphinx_search_form', $iid, $needle);
175 $sql = 'SELECT {sphinx_indexes}.*, {sphinx_attributes}.attribute_name AS sort_field FROM {sphinx_indexes} LEFT JOIN {sphinx_attributes} ON default_sort_key_fid = aid WHERE {sphinx_indexes}.iid=%d';
176
177 $res = db_query($sql, $iid);
178 $index = db_fetch_object($res);
179 $client = new SphinxClient();
180 $connect = $client->_Connect();
181 if (!$connect) {
182 drupal_set_message(variable_get('sphinx_offline_message', ''));
183 return;
184 }
185 if (!empty($_GET['as_sk'])) {
186 $sort = _sphinx_get_attr_by_aid($_GET['as_sk']);
187 }
188 else if (!empty($index->sort_field)) {
189 $sort = $index->sort_field;
190 }
191 else {
192 $sort = '';
193 }
194 if (!empty($sort)) {
195 if (!empty($_GET['as_sd'])) {
196 $order = ($_GET['as_sd'] == 'asc') ? 'asc' : 'desc';
197 }
198 elseif (!empty($index->default_sort_order)) {
199 $order = $index->default_sort_order;
200 }
201 else {
202 $order = 'desc';
203 }
204 }
205 $fields = _sphinx_get_active_fields_by_iid($iid);
206
207 foreach ($fields as $fid => $name) {
208 $term = $_GET['as_f'. $fid];
209 if (!empty($term)) {
210 $needle .= '@'. $name .' '. $term .' ';
211 }
212 }
213 if (!empty($_GET['as_filter'])) {
214 $filter_codes = explode('-', $_GET['as_filter']);
215 $filters = array();
216 for($z=0; $z<count($filter_codes); $z++){
217 $parts = explode('_',$filter_codes[$z]);
218
219 if(!empty($parts[0]) && !empty($parts[1])) {
220 $attr = _sphinx_get_attr_by_aid($parts[0]);
221 if(array_key_exists($attr, $filters)){
222 $filters[$attr][] = $parts[1];
223 } else {
224 $filters[$attr] = array($parts[1]);
225 }
226 }
227 }
228 }
229 if (!empty($needle)) {
230 if (isset($_GET['pr_page'])) {
231 $limit = (int)$_GET['pr_page'];
232 }
233 else {
234 $limit = variable_get('sphinx_results_per_page', '10');
235 }
236 $results = _sphinx_do_search($client, $needle, $index->index_name, $sort, $order, $filters, $limit);
237 $output .= theme_sphinx_results($results[0], $index->index_name, $needle, $index->excerpt);
238 $output .= _sphinx_pager($results[0], $limit);
239 }
240 return $output;
241 }
242
243 /**
244 * Do the search
245 *
246 *
247 * @param $client
248 * A SphinxClient Object
249 * @param $needle
250 * A string containing the word(s) to search for
251 * @param $index
252 * A string constaining the index(es) to search
253 * @param $sort
254 * A string constaining instructions for the sorting of results
255 *
256 * @return
257 * true if the address is in a valid format.
258 */
259 function _sphinx_do_search($client, $needle, $index, $sort, $order, $filters = null, $limit) {
260 if (!empty($sort)) {
261 $client->SetSortMode(SPH_SORT_EXTENDED, $sort.' '.$order);
262 } else {
263 $client->SetSortMode(SPH_SORT_RELEVANCE);
264 }
265 if(is_array($filters)){
266 foreach($filters as $attribute => $values){
267 for($x=0; $x<count($values); $x++){
268 $client->SetFilter( $attribute, array($values[$x]));
269 }
270 }
271 }
272 $client->SetMatchMode(SPH_MATCH_EXTENDED);
273 if (isset($_GET['page'])) {
274 $offset = (int)($_GET['page'] * $limit);
275 $client->SetLimits($offset, intval($limit));
276 }
277 else {
278 $client->SetLimits(0, intval($limit));
279 }
280 $client->AddQuery($needle, $index);
281 $response = $client->RunQueries();
282
283 return $response;
284 }
285
286 /**
287 * Render the search results
288 *
289 *
290 * @param $results
291 * An array returned by the Sphinx api
292 * @param $needle
293 * A string containing the word(s) to search for
294 *
295 * @return
296 * true if the address is in a valid format.
297 */
298 function theme_sphinx_results($results, $index, $needle, $show_excerpts) {
299 $client = new SphinxClient();
300 $output = '';
301 $output .= theme_sphinx_feedback($results, $needle);
302 if ($results['total_found'] > 0) {
303 $lines = array();
304 foreach ($results['matches'] as $k => $v) {
305 $node = node_load($k);
306 if ($node->nid) {
307 if ($show_excerpts) {
308 $fields = _sphinx_excerpt_fields($index);
309 //$content = _sphinx_excerpt_content($index, $node);
310 //TODO: need to figure out how db-fields are translated to arrays in order to retrieve the relevant fields
311 $excerpt = $client->BuildExcerpts(array($node->title, $node->field_brdtekst), $index, $needle, $opts = array());
312 //print_r($fields);
313 $lines[] = theme_sphinx_result($node, $excerpt, $fields);
314 }
315 else {
316 $lines[] = theme_sphinx_result($node);
317 }
318 }
319 }
320 }
321 $output = theme('item_list', $lines);
322 return $output;
323 }
324
325 function theme_sphinx_feedback($results, $needle) {
326 $output = '';
327 $output .= '<div class="sphinx-search-feedback">';
328 $output .= $results['total_found'] .' ';
329 $output .= ($results['total_found'] == 1) ? t('result') : t('results');
330 $output .= ' '. t('for');
331 $output .= '<span class="sphinx-search-term"> '. $needle .'</span> ('. $results['time'] .' '. t('secs.') .')';
332 $output .= '</div>';
333 return $output;
334 }
335
336 function theme_sphinx_result($node, $excerpt = null, $fields = null) {
337 if (is_array($excerpt)) {
338 return theme_sphinx_excerpt_result($node, $excerpt, $fields);
339 }
340 else {
341 return node_view($node, true);
342 }
343 }
344
345 function theme_sphinx_excerpt_result($node, $excerpt, $fields) {
346 $output = '';
347 if (is_array($excerpt)) {
348 $output .= '<div class="sphinx-field-'. $fields[0] .'">'. l($excerpt[0], 'node/'. $node->nid, array(), null, null, false, true) .'</div>';
349 for ($n = 1; $n < count($excerpt); $n++) {
350 $output .= '<div class="sphinx-field-'. $fields[$n] .'">'. $excerpt[$n] .'</div>';
351 }
352 }
353 return $output;
354 }
355
356 function _sphinx_pager($results, $limit) {
357 if ($results['total'] > 0) {
358 global $pager_total_items, $pager_total, $pager_page_array;
359 $pager_total_items[0] = (int) $results['total'];
360 $pager_total[0] = ceil($results['total'] / $limit);
361 $pager_page_array[0] = max(0, min((int) $_GET['page'], ($pager_total[0] - 1)));
362 }
363 $output = theme('pager');
364 return $output;
365 }
366
367 /**
368 * FAPI definition for the sphinx search form.
369 *
370 * ...
371 * @ingroup forms
372 * @see sphinx_search_form_validate()
373 * @see sphinx_search_form_submit()
374 */
375 function sphinx_search_form($iid, $needle) {
376
377 $sql = 'SELECT * FROM {sphinx_indexes} WHERE iid=%d AND active=1';
378 $result = db_query($sql, $iid);
379 $index = db_fetch_object($result);
380 /*$form['sphinx_search']['index'] = array(
381 '#value' => t('Search for !display_name', array('!display_name' => $index->display_name)),
382 '#weight' => -10,
383 );*/
384 $form['sphinx_search']['index_path'] = array(
385 '#type' => 'hidden',
386 '#value' => $index->path,
387 );
388 $form['sphinx_search']['iid'] = array(
389 '#type' => 'hidden',
390 '#value' => $iid,
391 );
392 $form['sphinx_search']['searchstring'] = array(
393 '#type' => 'textfield',
394 '#default_value' => $needle,
395 '#size' => 60,
396 '#maxlength' => 128,
397 '#required' => false,
398 '#weight' => -8,
399 );
400 $form['sphinx_search']['advanced'] = array(
401 '#type' => 'fieldset',
402 '#title' => t('Advanced search'),
403 '#collapsible' => true,
404 '#collapsed' => ($_GET['as'] == 1) ? false : true,
405 '#weight' => -6,
406 );
407
408 $sql = 'SELECT aid, attribute_name, display_name FROM {sphinx_attributes} WHERE iid=%d AND active=1';
409 $result = db_query($sql, $iid);
410 $options = array(0 => '');
411 while ($attributes = db_fetch_object($result)) {
412
413 $options[$attributes->aid] = $attributes->display_name;
414 }
415 $sql = 'SELECT fid, field_name, display_name FROM {sphinx_fields} WHERE iid=%d AND active=1 ORDER BY weight';
416 $result = db_query($sql, $iid);
417 $count = -40;
418 while ($fields = db_fetch_object($result)) {
419
420 $form['sphinx_search']['advanced']['field'][$fields->field_name] = array(
421 '#title' => $fields->display_name,
422 '#type' => 'textfield',
423 '#default_value' => (!empty($_GET['as_f'. $fields->fid])) ? $_GET['as_f'. $fields->fid] : '',
424 '#required' => false,
425 '#weight' => $count,
426 );
427 $count+=2;
428 }
429 $form['sphinx_search']['advanced']['sort_key'] = array(
430 '#type' => 'select',
431 '#title' => t('Sort'),
432 '#options' => $options,
433 '#default_value' => (!empty($_GET['as_sk'])) ? $_GET['as_sk'] : '',
434 '#weight' => 50,
435 //'#description' => t('Select what you want to order by'),
436 );
437 $form['sphinx_search']['advanced']['sort_direction'] = array(
438 '#type' => 'select',
439 '#title' => t('Order'),
440 '#options' => array('asc' => t('Ascending'), 'desc' => t('Descending')),
441 '#default_value' => (!empty($_GET['as_sd'])) ? $_GET['as_sd'] : '',
442 '#weight' => 60,
443 );
444
445 $form['sphinx_search']['submit'] = array('#type' => 'submit', '#value' => t('Search'), '#weight' => 2,);
446
447
448 return $form;
449 }
450
451 function sphinx_search_form_validate($form_id, $form_values) {
452 $search = $form_values['searchstring'];
453 $sql = 'SELECT fid,field_name FROM {sphinx_fields} WHERE iid=%d AND active=1 ORDER BY weight DESC';
454 $res = db_query($sql, $form_values['iid']);
455 while ($fields = db_fetch_object($res)) {
456 $field = $form_values[$fields->field_name];
457 if (!empty($field)) {
458 $search .= $field;
459 }
460 }
461 if (empty($search)) {
462 form_set_error($form_values['searchstring'], t('You must enter a search string'));
463 }
464 }
465
466 function sphinx_search_form_submit($form_id, $form_values) {
467 $query = _sphinx_build_advanced_query($form_values);
468 drupal_goto('search/'. $form_values['index_path'] .'/'. $form_values['searchstring'], $query);
469 }
470
471 function _sphinx_build_advanced_query($form_values) {
472 $output = '';
473 $sql = 'SELECT fid,field_name FROM {sphinx_fields} WHERE iid=%d AND active=1 ORDER BY weight DESC';
474 $res = db_query($sql, $form_values['iid']);
475 while ($fields = db_fetch_object($res)) {
476 $field = $form_values[$fields->field_name];
477 if (!empty($field)) {
478 $output .= 'as_f'. $fields->fid .'='. $field .'&';
479 }
480 }
481 if ($form_values['sort_key']) {
482 $output .= 'as_sk='. $form_values['sort_key'] .'&as_sd='. $form_values['sort_direction'] .'&';
483 }
484 if (!empty($output)) {
485 return 'as=1&'. substr($output, 0, -1);
486 }
487 else {
488 return null;
489 }
490 }
491
492 function _sphinx_excerpt_fields($index) {
493 $output = array();
494 $sql = 'SELECT field_name FROM {sphinx_fields} WHERE iid=%d AND excerpt=1 ORDER BY weight DESC';
495 $res = db_query($sql, _sphinx_get_index_by_name($index));
496 while ($fields = db_fetch_object($res)) {
497 $output[] = strtolower($fields->field_name);
498 }
499 return $output;
500 }
501

  ViewVC Help
Powered by ViewVC 1.1.2