comparison solrsearch_search.admin.inc @ 0:a2b4f67e73dc default tip

initial
author Dirk Wintergruen <dwinter@mpiwg-berlin.mpg.de>
date Mon, 08 Jun 2015 10:21:54 +0200
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:a2b4f67e73dc
1 <?php
2
3 /**
4 * @file
5 * Administrative settings for searching.
6 */
7
8 /**
9 * Helper function for empty search configuration.
10 */
11 function _solrsearch_search_browse_form($default_value) {
12 $description = t('This is what is shown when the user enters an empty search, or removes all filters from an active search.') . ' ';
13 if (!module_exists('facetapi')) {
14 $description .= t('<strong>Facets will not be shown until you enable Facet API module.</strong>');
15 }
16 else {
17 $description .= t('Remember to configure the facets on the <a href="!facetslink">search environment page</a> and assign blocks to regions on the <a href="!blocklink">block settings page</a>', array(
18 '!facetslink' => url('admin/config/search/solrsearch/settings/'),
19 '!blocklink' => url('admin/structure/block'),
20 ));
21 }
22 return array(
23 '#type' => 'radios',
24 '#title' => t('Behavior on empty search'),
25 '#options' => array(
26 'none' => t("Show search box"),
27 'browse' => t("Show enabled facets' blocks under the search box"),
28 'blocks' => t("Show enabled facets' blocks in their configured regions"),
29 'results' => t("Show enabled facets' blocks in their configured regions and first page of all available results"),
30 ),
31 '#default_value' => $default_value,
32 '#description' => $description,
33 );
34 }
35
36 /**
37 * Menu callback for the overview page showing custom search pages and blocks.
38 * @return array $build
39 */
40 function solrsearch_search_page_list_all() {
41
42 $build['pages'] = solrsearch_search_page_list_pages();
43 $build['blocks'] = solrsearch_search_page_list_blocks();
44 return $build;
45
46 }
47
48
49 /**
50 * Listing of all the search pages
51 * @return array $build
52 */
53 function solrsearch_search_page_list_pages() {
54 $build = array();
55 $rows = array();
56 $rows['core_solr_search'] = array();
57
58 // Build the sortable table header.
59 $header = array(
60 'label' => array('data' => t('Name'), 'field' => 's.label'),
61 'path' => array('data' => t('Path'), 'field' => 's.search_path'),
62 'environment' => array('data' => t('Search environment')),
63 'operations' => array('data' => t('Operations')),
64 );
65
66 $search_pages = solrsearch_search_load_all_search_pages();
67 $default_search_page = solrsearch_search_default_search_page();
68 foreach ($search_pages as $search_page) {
69 $row = array();
70
71 // Add the label
72 $label = check_plain($search_page['label']);
73 // Is this row our default environment?
74 if ($search_page['page_id'] == $default_search_page) {
75 $label = t('!search_page <em>(Default)</em>', array('!search_page' => $label));
76 }
77
78 $row[] = $label;
79 // Add the link
80 $row[] = array(
81 'data' => array(
82 '#type' => 'link',
83 '#title' => $search_page['search_path'],
84 '#href' => $search_page['search_path'],
85 ),
86 );
87
88 // Add the search environment
89 $environment = solrsearch_environment_load($search_page['env_id']);
90 $row[] = $environment ? check_plain($environment['name']) : check_plain(t('<Disabled>'));
91 // Operations
92 $row[] = array('data' => l(t('Edit'), 'admin/config/search/solrsearch/search-pages/' . $search_page['page_id'] . '/edit'));
93 $row[] = array('data' => l(t('Clone'), 'admin/config/search/solrsearch/search-pages/' . $search_page['page_id'] . '/clone'));
94
95 // Allow to revert a search page or to delete it
96 if (!isset($search_page['settings']['solrsearch_search_not_removable']) && !isset($search_page['in_code_only'])) {
97 if ((isset($search_page['type']) && $search_page['type'] == 'Overridden')) {
98 $row[] = array('data' => l(t('Revert'), 'admin/config/search/solrsearch/search-pages/' . $search_page['page_id'] . '/delete'));
99 } else {
100 $row[] = array('data' => l(t('Delete'), 'admin/config/search/solrsearch/search-pages/' . $search_page['page_id'] . '/delete'));
101 }
102 }
103 else {
104 $row[] = '';
105 }
106 $rows[$search_page['page_id']] = $row;
107 }
108
109 // Automatically enlarge our header with the operations size
110 $header['operations']['colspan'] = count(reset($rows)) - 3;
111
112 $build['list'] = array(
113 '#prefix' => '<h3>Pages</h3>',
114 '#theme' => 'table',
115 '#header' => $header,
116 '#rows' => array_values($rows),
117 '#empty' => t('No available search pages.'),
118 );
119 $build['pager'] = array(
120 '#theme' => 'pager',
121 '#quantity' => 20,
122 '#weight' => 10,
123 );
124
125 return $build;
126 }
127
128 /**
129 * Listing of all the search blocks
130 * @return array $build
131 */
132 function solrsearch_search_page_list_blocks() {
133 $build = array();
134 $rows = array();
135
136 // Build the sortable table header.
137 $header = array(
138 'label' => array('data' => t('Name'), 'field' => 's.label'),
139 'environment' => array('data' => t('Search environment')),
140 'operations' => array('data' => t('Operations')),
141 );
142
143 $search_blocks = variable_get('solrsearch_search_mlt_blocks', array());
144 foreach ($search_blocks as $search_block_id => $search_block) {
145 $row = array();
146
147 // Add the label
148 $label = check_plain($search_block['name']);
149 $row[] = $label;
150
151 // Add the search environment
152 $environment = solrsearch_environment_load($search_block['mlt_env_id']);
153 $row[] = $environment ? check_plain($environment['name']) : check_plain(t('<Disabled>'));
154 // Operations
155 if (module_exists('block')) {
156 $row[] = array('data' => l(t('Configure'), 'admin/structure/block/manage/solrsearch_search/' . $search_block_id . '/configure', array('query' => array('destination' => current_path()))));
157 }
158 $row[] = array('data' => l(t('Delete'), 'admin/config/search/solrsearch/search-pages/block/' . $search_block_id . '/delete'));
159 $rows[$search_block_id] = $row;
160 }
161
162 // Automatically enlarge our header with the operations size
163 $header['operations']['colspan'] = count(reset($rows)) - 2;
164
165 $build['list'] = array(
166 '#prefix' => '<h3>Blocks "More Like This"</h3>',
167 '#theme' => 'table',
168 '#header' => $header,
169 '#rows' => array_values($rows),
170 '#empty' => t('No available search blocks.'),
171 );
172 $build['pager'] = array(
173 '#theme' => 'pager',
174 '#quantity' => 20,
175 '#weight' => 10,
176 );
177
178 return $build;
179 }
180
181 /**
182 * Menu callback/form-builder for the form to create or edit a search page.
183 */
184 function solrsearch_search_page_settings_form($form, &$form_state, $search_page = NULL) {
185 $environments = solrsearch_load_all_environments();
186 $options = array('' => t('<Disabled>'));
187 foreach ($environments as $id => $environment) {
188 $options[$id] = $environment['name'];
189 }
190 // Validate the env_id.
191 if (!empty($search_page['env_id']) && !solrsearch_environment_load($search_page['env_id'])) {
192 $search_page['env_id'] = '';
193 }
194
195 // Initializes form with common settings.
196 $form['search_page'] = array(
197 '#type' => 'value',
198 '#value' => $search_page,
199 );
200
201 $form['label'] = array(
202 '#type' => 'textfield',
203 '#title' => t('Label'),
204 '#description' => '',
205 '#required' => TRUE,
206 '#size' => 30,
207 '#maxlength' => 32,
208 '#default_value' => !empty($search_page['label']) ? $search_page['label'] : '',
209 '#description' => t('The human-readable name of the search page configuration.'),
210 );
211
212 $form['page_id'] = array(
213 '#type' => 'machine_name',
214 '#maxlength' => 32,
215 '#required' => TRUE,
216 '#machine_name' => array(
217 'exists' => 'solrsearch_search_page_exists',
218 'source' => array('label'),
219 ),
220 '#description' => '',
221 '#default_value' => !empty($search_page['page_id']) ? $search_page['page_id'] : '',
222 '#disabled' => !empty($search_page),
223 '#description' => t('A unique machine-readable identifier for the search page configuration. It must only contain lowercase letters, numbers, and underscores.'),
224 );
225
226 $form['description_enable'] = array(
227 '#type' => 'checkbox',
228 '#title' => t('Description'),
229 '#default_value' => !empty($search_page['description']) ? TRUE : FALSE
230 );
231
232 $form['description'] = array(
233 '#type' => 'textfield',
234 '#title' => t('Provide description'),
235 '#title_display' => 'invisible',
236 '#size' => 64,
237 '#default_value' => !empty($search_page['description']) ? $search_page['description'] : '',
238 '#dependency' => array(
239 'edit-description-enable' => array(1),
240 ),
241 );
242
243 $is_default = FALSE;
244 if (!empty($search_page)) {
245 $is_default = $search_page['page_id'] == solrsearch_search_default_search_page();
246 }
247 $form['make_default'] = array(
248 '#type' => 'checkbox',
249 '#title' => t('Make this Solr Search Page the default'),
250 '#description' => t('Useful for eg. making facets to link to this page when they are shown on non-search pages'),
251 '#default_value' => $is_default,
252 '#disabled' => $is_default,
253 );
254
255 $form['info'] = array(
256 '#title' => t('Search Page Information'),
257 '#type' => 'fieldset',
258 '#collapsible' => FALSE,
259 '#prefix' => '<div id="dynamic-search-page">',
260 '#suffix' => '</div>',
261 );
262
263 $core_solr_search = FALSE;
264 if (!empty($search_page['page_id']) && ($search_page['page_id'] == 'core_solr_search')) {
265 $core_solr_search = TRUE;
266 }
267 if ($core_solr_search) {
268 $description = t('This page always uses the current default search environment');
269 }
270 else {
271 $description = t('The environment that is used by this search page. If no environment is selected, this page will be disabled.');
272 }
273
274 $form['info']['env_id'] = array(
275 '#title' => t('Search environment'),
276 '#type' => 'select',
277 '#options' => $options,
278 '#default_value' => !empty($search_page['env_id']) ? $search_page['env_id'] : '',
279 '#disabled' => $core_solr_search,
280 '#description' => $description,
281 );
282
283 $form['info']['page_title'] = array(
284 '#title' => t('Title'),
285 '#type' => 'textfield',
286 '#required' => TRUE,
287 '#maxlength' => 255,
288 '#description' => 'You can use %value to place the search term in the title',
289 '#default_value' => !empty($search_page['page_title']) ? $search_page['page_title'] : '',
290 );
291
292 $search_types = solrsearch_search_load_all_search_types();
293 $options = array('custom' => t('Custom Field'));
294 foreach ($search_types as $id => $search_type) {
295 $options[$id] = $search_type['name'];
296 }
297
298 $form['info']['search_type'] = array(
299 '#title' => t('Search Type'),
300 '#type' => 'select',
301 '#options' => $options,
302 '#default_value' => !empty($search_page['settings']['solrsearch_search_search_type']) ? $search_page['settings']['solrsearch_search_search_type'] : '',
303 '#access' => !$core_solr_search,
304 '#description' => t('Use this only when filtering on a value from the search path.
305 For example, select Taxonomy Term to filter on a term ID (search/taxonomy/%).'),
306 '#ajax' => array(
307 'callback' => 'solrsearch_search_ajax_search_page_default',
308 'wrapper' => 'dynamic-search-page',
309 'method' => 'replace',
310 ),
311 );
312
313 // Token element validate is added to validate the specific
314 // tokens that are allowed
315 $form['info']['search_path'] = array(
316 '#title' => t('Path'),
317 '#type' => 'textfield',
318 '#required' => TRUE,
319 '#maxlength' => 255,
320 '#description' => t('For example: search/my-search-page. Search keywords will appear at the end of the path.'),
321 '#default_value' => !empty($search_page['search_path']) ? $search_page['search_path'] : '',
322 );
323 if (!$core_solr_search) {
324 $form['info']['search_path']['#description'] .= ' ' . t('You can use one % to make the search page dynamic.');
325 }
326
327 $form['info']['custom_filter_enable'] = array(
328 '#type' => 'checkbox',
329 '#title' => t('Custom Filter'),
330 '#default_value' => !empty($search_page['settings']['solrsearch_search_custom_enable']) ? TRUE : FALSE
331 );
332
333 $form['info']['filters'] = array(
334 '#title' => t('Custom filters'),
335 '#type' => 'textfield',
336 '#required' => FALSE,
337 '#maxlength' => 255,
338 '#description' => t('A comma-separated list of lucene filter queries to apply by default.'),
339 '#default_value' => !empty($search_page['settings']['fq']) ? implode(', ', $search_page['settings']['fq']) : '',
340 '#dependency' => array(
341 'edit-custom-filter-enable' => array(1),
342 'edit-search-type' => array('custom'),
343 ),
344 );
345 if (!$core_solr_search) {
346 $form['info']['filters']['#description'] .= ' ' . t('E.g. "bundle:blog, is_uid:(1 OR 2 OR %). % will be replaced by the value of % in the path"');
347 }
348
349 $form['advanced'] = array(
350 '#title' => t('Advanced Search Page Options'),
351 '#type' => 'fieldset',
352 '#collapsible' => TRUE,
353 '#collapsed' => TRUE,
354 '#tree' => TRUE,
355 );
356
357 // Results per page per search page
358 $default_value = isset($search_page['settings']['solrsearch_search_per_page']) ? $search_page['settings']['solrsearch_search_per_page'] : '10';
359 $form['advanced']['solrsearch_search_per_page'] = array(
360 '#type' => 'textfield',
361 '#size' => 3,
362 '#title' => t('Results per page'),
363 '#description' => t('How many items will be displayed on one page of the search result.'),
364 '#default_value' => $default_value,
365 );
366
367 // Enable/disable spellcheck on pages
368 $default_value = isset($search_page['settings']['solrsearch_search_spellcheck']) ? $search_page['settings']['solrsearch_search_spellcheck'] : TRUE;
369 $form['advanced']['solrsearch_search_spellcheck'] = array(
370 '#type' => 'checkbox',
371 '#title' => t('Enable spell check'),
372 '#description' => t('Display "Did you mean … ?" above search results.'),
373 '#default_value' => $default_value,
374 );
375
376 // Enable/disable search form on search page (replaced by a block perhaps)
377 $default_value = isset($search_page['settings']['solrsearch_search_search_box']) ? $search_page['settings']['solrsearch_search_search_box'] : TRUE;
378 $form['advanced']['solrsearch_search_search_box'] = array(
379 '#type' => 'checkbox',
380 '#title' => t('Enable the search box on the page'),
381 '#description' => t('Display a search box on the page.'),
382 '#default_value' => $default_value,
383 );
384
385 // Enable/disable search form on search page (replaced by a block perhaps)
386 $default_value = isset($search_page['settings']['solrsearch_search_allow_user_input']) ? $search_page['settings']['solrsearch_search_allow_user_input'] : FALSE;
387 $form['advanced']['solrsearch_search_allow_user_input'] = array(
388 '#type' => 'checkbox',
389 '#title' => t('Allow user input using the URL'),
390 '#description' => t('Allow users to use the URL for manual facetting via fq[] params (e.g. http://example.com/search/site/test?fq[]=uid:1&fq[]=tid:99). This will only work in combination with a keyword search. The recommended value is unchecked'),
391 '#default_value' => $default_value,
392 );
393
394 // Use the main search page setting as the default for new pages.
395 $default_value = isset($search_page['settings']['solrsearch_search_browse']) ? $search_page['settings']['solrsearch_search_browse'] : 'browse';
396 $form['advanced']['solrsearch_search_browse'] = _solrsearch_search_browse_form($default_value);
397
398 // Button for the corresponding actions
399 $form['actions'] = array(
400 '#type' => 'actions',
401 );
402
403 $form['actions']['submit'] = array(
404 '#type' => 'submit',
405 '#redirect' => 'admin/config/search/solrsearch/search-pages',
406 '#value' => t('Save'),
407 );
408 $form['actions']['submit_edit'] = array(
409 '#type' => 'submit',
410 '#value' => t('Save and edit'),
411 );
412
413 $form['actions']['cancel'] = array(
414 '#type' => 'link',
415 '#title' => t('Cancel'),
416 '#href' => 'admin/config/search/solrsearch/search-pages',
417 );
418
419 $form['#submit'][] = 'solrsearch_search_page_settings_form_submit';
420
421 return $form;
422 }
423
424 /**
425 * Callback element needs only select the portion of the form to be updated.
426 * Since #ajax['callback'] return can be HTML or a renderable array (or an
427 * array of commands), we can just return a piece of the form.
428 */
429 function solrsearch_search_ajax_search_page_default($form, $form_state, $search_page = NULL) {
430
431 $search_page = $form_state['values']['search_page'];
432 $search_types = solrsearch_search_load_all_search_types();
433
434 // Helping with sensible defaults for the search path
435 $default_search_path = '';
436 if (!empty($form_state['values']['search_type']) && $form_state['values']['search_type'] != 'custom') {
437 $default_search_path = $search_types[$form_state['values']['search_type']]['default menu'];
438 $form['info']['search_path']['#value'] = $default_search_path;
439 }
440
441 // Helping with sensible defaults for the search title
442 $default_search_title = '';
443
444 if (empty($form_state['values']['page_title']) && $form_state['values']['search_type'] != 'custom') {
445 $default_search_title_callback = $search_types[$form_state['values']['search_type']]['title callback'];
446 $default_search_title = $default_search_title_callback();
447 $form['info']['page_title']['#value'] = $default_search_title;
448 }
449 return $form['info'];
450 }
451
452 function solrsearch_search_page_settings_form_validate($form, &$form_state) {
453 // Performs basic validation of the menu path.
454 if (url_is_external($form_state['values']['search_path'])) {
455 form_set_error('search_path', t('Path must be local.'));
456 }
457 $form_state['values']['search_path'] = trim($form_state['values']['search_path'], '/');
458 if (empty($form_state['values']['search_path'])) {
459 form_set_error('search_path', t('Path required.'));
460 }
461 if (!is_numeric($form_state['values']['advanced']['solrsearch_search_per_page'])) {
462 form_set_error('advanced][solrsearch_search_per_page', t('The amount of search results must be an integer.'));
463 }
464 $form_state['values']['advanced']['solrsearch_search_per_page'] = (int) $form_state['values']['advanced']['solrsearch_search_per_page'];
465 if (empty($form_state['values']['advanced']['solrsearch_search_per_page'])) {
466 form_set_error('advanced][solrsearch_search_per_page', t('The amount of search results cannot be empty.'));
467 }
468 if (count(explode('%', $form_state['values']['search_path'])) > 2) {
469 form_set_error('search_path', t('Only one % placeholder is allowed.'));
470 }
471 }
472
473 /**
474 * Processes solrsearch_search_page_settings_form form submissions.
475 */
476 function solrsearch_search_page_settings_form_submit($form, &$form_state) {
477 $settings = array();
478 $settings['fq'] = array();
479 if ($form_state['values']['filters']) {
480 foreach (explode(',', $form_state['values']['filters']) as $string) {
481 $string = trim($string);
482 // Minimal validation. ':' must exist and can't be the 1st char..
483 if (strpos($string, ':')) {
484 $settings['fq'][] = $string;
485 }
486 }
487 }
488 $settings['solrsearch_search_custom_enable'] = $form_state['values']['custom_filter_enable'];
489 $settings['solrsearch_search_search_type'] = $form_state['values']['search_type'];
490 // Add all advanced settings.
491 $settings += $form_state['values']['advanced'];
492
493 // Set the default search page settings
494 if (!empty($form_state['values']['make_default']) && isset($form_state['values']['page_id'])) {
495 variable_set('solrsearch_search_default_search_page', $form_state['values']['page_id']);
496 }
497
498 $search_page = array();
499 $search_page['page_id'] = $form_state['values']['page_id'];
500 $search_page['label'] = $form_state['values']['label'];
501 $search_page['description'] = $form_state['values']['description'];
502 $search_page['env_id'] = $form_state['values']['env_id'];
503 $search_page['search_path'] = $form_state['values']['search_path'];
504 $search_page['page_title'] = $form_state['values']['page_title'];
505 $search_page['settings'] = $settings;
506 solrsearch_search_page_save($search_page);
507
508 // Saves our values in the database, sets redirect path on success.
509 drupal_set_message(t('The configuration options have been saved for %page.', array('%page' => $form_state['values']['label'])));
510 if (isset($form_state['clicked_button']['#redirect'])) {
511 $form_state['redirect'] = $form_state['clicked_button']['#redirect'];
512 }
513 else {
514 $form_state['redirect'] = current_path();
515 }
516 // Regardlessly of the destination parameter we want to go to another page
517 unset($_GET['destination']);
518 drupal_static_reset('drupal_get_destination');
519 drupal_get_destination();
520 // Menu rebuild needed to pick up search path.
521 menu_rebuild();
522 }
523
524 /**
525 * Deletes a single search page configuration.
526 */
527 function solrsearch_search_delete_search_page_confirm($form, &$form_state, $search_page) {
528
529 // Sets values required for deletion.
530 $form['page_id'] = array('#type' => 'value', '#value' => $search_page['page_id']);
531 $form['label'] = array('#type' => 'value', '#value' => $search_page['label']);
532
533 if (isset($search_page['export_type']) && $search_page['export_type'] == '3') {
534 $verb = t('Revert');
535 }
536 else {
537 $verb = t('Delete');
538 }
539
540 // Sets the message, or the title of the page.
541 $message = t(
542 'Are you sure you want to !verb the %label search page configuration?',
543 array('%label' => $form['label']['#value'], '!verb' => strtolower($verb))
544 );
545
546
547 // Builds caption.
548 $caption = '<p>';
549 $caption .= t(
550 'The %label search page configuration will be deleted.',
551 array('%label' => $form['label']['#value'])
552 );
553 $caption .= '</p>';
554 $caption .= '<p><strong>' . t('This action cannot be undone.') . '</strong></p>';
555
556 // Finalizes and returns the confirmation form.
557 $return_path = 'admin/config/search/solrsearch/search-pages';
558 $button_text = $verb;
559 if (!isset($search_page['settings']['solrsearch_search_not_removable'])) {
560 return confirm_form($form, filter_xss($message), $return_path, filter_xss($caption), check_plain($button_text));
561 }
562 else {
563 // Maybe this should be solved somehow else
564 drupal_access_denied();
565 }
566 }
567
568 /**
569 * Process content type delete confirm submissions.
570 */
571 function solrsearch_search_delete_search_page_confirm_submit($form, &$form_state) {
572 // Deletes the index configuration settings.
573 // @todo Invoke a hook that allows backends and indexers to delete their stuff.
574 db_delete('solrsearch_search_page')
575 ->condition('page_id', $form_state['values']['page_id'])
576 ->execute();
577
578 // Sets message, logs action.
579 drupal_set_message(t(
580 'The %label search page configuration has been deleted.',
581 array('%label' => $form_state['values']['label'])
582 ));
583 watchdog('solrsearch_search', 'Deleted search page configuration "@page_id".', array('@page_id' => $form_state['values']['page_id']), WATCHDOG_NOTICE);
584
585 // Rebuilds the menu cache.
586 menu_rebuild();
587
588 // Returns back to search page list page.
589 $form_state['redirect'] = 'admin/config/search/solrsearch/search-pages';
590 }
591
592 /**
593 * Clones a single search page configuration
594 * @param $search_page
595 * The search page that needs to be cloned
596 */
597 function solrsearch_search_clone_search_page_confirm($form, &$form_state, $search_page) {
598 $form['page_id'] = array(
599 '#type' => 'value',
600 '#value' => $search_page['page_id'],
601 );
602 return confirm_form(
603 $form,
604 t('Are you sure you want to clone search page %name?', array('%name' => $search_page['label'])),
605 'admin/config/search/solrsearch',
606 '',
607 t('Clone'),
608 t('Cancel')
609 );
610 }
611
612 /**
613 * Submits the confirmations of the cloning of a search page
614 */
615 function solrsearch_search_clone_search_page_confirm_submit($form, &$form_state) {
616 if (solrsearch_search_page_clone($form_state['values']['page_id'])) {
617 drupal_set_message(t('The search page was cloned'));
618 }
619 $form_state['redirect'] = 'admin/config/search/solrsearch/search-pages';
620 }
621
622 /**
623 * Menu callback - the settings form.
624 */
625 function solrsearch_search_get_fields($environment = NULL) {
626 if (empty($environment)) {
627 $env_id = solrsearch_default_environment();
628 $environment = solrsearch_environment_load($env_id);
629 }
630 $env_id = $environment['env_id'];
631
632 // Try to fetch the schema fields.
633 try {
634 $solr = solrsearch_get_solr($env_id);
635 $fields = $solr->getFields();
636 return $fields;
637 }
638 catch (Exception $e) {
639 watchdog('Apache Solr', nl2br(check_plain($e->getMessage())), NULL, WATCHDOG_ERROR);
640 drupal_set_message(nl2br(check_plain($e->getMessage())), 'warning');
641 drupal_set_message(t('Cannot get information about the fields in the index.'), 'warning');
642 }
643 }
644
645 /**
646 * Menu callback - Bias settings form.
647 */
648 function solrsearch_bias_settings_page($environment = NULL) {
649 if (empty($environment)) {
650 $env_id = solrsearch_default_environment();
651 $environment = solrsearch_environment_load($env_id);
652 }
653 $env_id = $environment['env_id'];
654
655 // Initializes output with information about which environment's setting we are
656 // editing, as it is otherwise not transparent to the end user.
657 $output = array(
658 'solrsearch_environment' => array(
659 '#theme' => 'solrsearch_settings_title',
660 '#env_id' => $env_id,
661 ),
662 );
663
664 // Adds content bias and type boost forms.
665 $fields = solrsearch_search_get_fields($environment);
666 $form = array();
667 $form = drupal_get_form('solrsearch_search_bias_form', $env_id, $fields);
668 $output['bias_forms'] = $form;
669 return $output;
670 }
671
672 function solrsearch_search_bias_form($form, &$form_state, $env_id, $fields) {
673 $form['#env_id'] = $env_id;
674 $form['bias_tabs'] = array(
675 '#type' => 'vertical_tabs',
676 );
677 $form['actions']['#type'] = 'actions';
678 $form['actions']['submit'] = array(
679 '#type' => 'submit',
680 '#value' => t('Save configuration'),
681 '#submit' => array('solrsearch_search_bias_form_submit'),
682 );
683 $form['actions']['reset'] = array(
684 '#type' => 'submit',
685 '#value' => t('Reset to defaults'),
686 '#submit' => array('solrsearch_search_bias_form_reset'),
687 );
688 $form += solrsearch_search_result_bias_form($env_id);
689 $form += solrsearch_search_type_boost_form($env_id);
690 $form += solrsearch_search_field_bias_form($fields, $env_id);
691 return $form;
692 }
693
694 function solrsearch_search_bias_form_submit(&$form, &$form_state) {
695 // Exclude unnecessary elements.
696 form_state_values_clean($form_state);
697 foreach ($form_state['values'] as $key => $value) {
698 if (is_array($value) && isset($form_state['values']['array_filter'])) {
699 $value = array_keys(array_filter($value));
700 }
701 // There is no need to set default variable values.
702 if (!isset($form[$key]['#default_value']) || $form[$key]['#default_value'] != $value) {
703 switch ($key) {
704 case 'solrsearch_search_sticky_boost' :
705 case 'solrsearch_search_promote_boost' :
706 case 'solrsearch_search_date_boost' :
707 case 'solrsearch_search_comment_boost' :
708 case 'solrsearch_search_changed_boost' :
709 case 'solrsearch_search_type_boosts' :
710 case 'field_bias' :
711 solrsearch_environment_variable_set($form['#env_id'], $key, $value);
712 }
713 }
714 }
715 drupal_set_message(t('The configuration options have been saved.'));
716 }
717
718 function solrsearch_search_bias_form_reset($form, &$form_state) {
719 // Exclude unnecessary elements.
720 form_state_values_clean($form_state);
721
722 foreach ($form_state['values'] as $key => $value) {
723 solrsearch_environment_variable_del($form['#env_id'], $key);
724 }
725 drupal_set_message(t('The configuration options have been reset to their default values.'));
726 }
727
728 /**
729 * Form builder function to set date, comment, etc biases.
730 */
731 function solrsearch_search_result_bias_form($env_id) {
732
733 $date_settings = solrsearch_environment_variable_get($env_id, 'solrsearch_search_date_boost', '0:0');
734 $comment_settings = solrsearch_environment_variable_get($env_id, 'solrsearch_search_comment_boost', '0:0');
735 $changed_settings = solrsearch_environment_variable_get($env_id, 'solrsearch_search_changed_boost', '0:0');
736 $sticky_boost = solrsearch_environment_variable_get($env_id, 'solrsearch_search_sticky_boost', '0');
737 $promote_boost = solrsearch_environment_variable_get($env_id, 'solrsearch_search_promote_boost', '0');
738
739 $options = array(
740 '10:2000.0' => '10',
741 '8:1000.0' => '9',
742 '8:700.0' => '8',
743 '8:500.0' => '7',
744 '4:300.0' => '6',
745 '4:200.0' => '5',
746 '4:150.0' => '4',
747 '2:150.0' => '3',
748 '2:100.0' => '2',
749 '1:100.0' => '1',
750 '0:0' => t('Ignore'),
751 );
752
753 $weights = drupal_map_assoc(array('21.0', '13.0', '8.0', '5.0', '3.0', '2.0', '1.0', '0.8', '0.5', '0.3', '0.2', '0.1'));
754 $weights['0'] = t('Ignore');
755
756 $form = array();
757 $form['result_bias'] = array(
758 '#type' => 'fieldset',
759 '#title' => t('Result biasing'),
760 '#collapsible' => TRUE,
761 '#collapsed' => FALSE,
762 '#description' => t('Give bias to certain properties when ordering the search results. Any value except <em>Ignore</em> will increase the score of the given type in search results. Choose <em>Ignore</em> to ignore any given property.'),
763 '#group' => 'bias_tabs',
764 );
765 $form['result_bias']['solrsearch_search_sticky_boost'] = array(
766 '#type' => 'select',
767 '#options' => $weights,
768 '#title' => t("Sticky at top of lists"),
769 '#default_value' => $sticky_boost,
770 '#description' => t("Select additional bias to give to nodes that are set to be 'Sticky at top of lists'."),
771 );
772 $form['result_bias']['solrsearch_search_promote_boost'] = array(
773 '#type' => 'select',
774 '#options' => $weights,
775 '#title' => t("Promoted to home page"),
776 '#default_value' => $promote_boost,
777 '#description' => t("Select additional bias to give to nodes that are set to be 'Promoted to home page'."),
778 );
779 $form['result_bias']['solrsearch_search_date_boost'] = array(
780 '#type' => 'select',
781 '#options' => $options,
782 '#title' => t("More recently created"),
783 '#default_value' => $date_settings,
784 '#description' => t('This setting will change the result scoring so that nodes created more recently may appear before those with higher keyword matching.'),
785 );
786 $form['result_bias']['solrsearch_search_comment_boost'] = array(
787 '#type' => 'select',
788 '#options' => $options,
789 '#title' => t("More comments"),
790 '#default_value' => $comment_settings,
791 '#description' => t('This setting will change the result scoring so that nodes with more comments may appear before those with higher keyword matching.'),
792 );
793 $form['result_bias']['solrsearch_search_changed_boost'] = array(
794 '#type' => 'select',
795 '#options' => $options,
796 '#title' => t("More recent comments"),
797 '#default_value' => $changed_settings,
798 '#description' => t('This setting will change the result scoring so that nodes with the most recent comments (or most recent updates to the node itself) may appear before those with higher keyword matching.'),
799 );
800 return $form;
801 }
802
803 /**
804 * Form builder function to set query field weights.
805 */
806 function solrsearch_search_field_bias_form($fields, $env_id) {
807 $form = array();
808 // get the current weights
809 $defaults = array(
810 'content' => '1.0',
811 'ts_comments' => '0.5',
812 'tos_content_extra' => '0.1',
813 'label' => '5.0',
814 'tos_name' => '3.0',
815 'taxonomy_names' => '2.0',
816 'tags_h1' => '5.0',
817 'tags_h2_h3' => '3.0',
818 'tags_h4_h5_h6' => '2.0',
819 'tags_inline' => '1.0',
820 'tags_a' => '0',
821 );
822 $qf = solrsearch_environment_variable_get($env_id, 'field_bias', $defaults);
823 $weights = drupal_map_assoc(array('21.0', '13.0', '8.0', '5.0', '3.0', '2.0', '1.0', '0.8', '0.5', '0.3', '0.2', '0.1'));
824 $weights['0'] = t('Omit');
825 if (!$qf) {
826 $qf = $defaults;
827 }
828 if ($fields) {
829 $form['field_bias'] = array(
830 '#type' => 'fieldset',
831 '#title' => t('Field biases'),
832 '#collapsible' => TRUE,
833 '#collapsed' => FALSE,
834 '#tree' => TRUE,
835 '#description' => t('Specify here which fields are more important when searching. Give a field a greater numeric value to make it more important. If you omit a field, it will not be searched.'),
836 '#group' => 'bias_tabs',
837 );
838 foreach ($fields as $field_name => $field) {
839 // Only indexed feids are searchable.
840 if ($field->schema{0} == 'I') {
841 // By default we only show text fields. Use hook_form_alter to change.
842 // We use filter_xss to make sure links are allowed
843 $form['field_bias'][$field_name] = array(
844 '#access' => ($field->type == 'text' || $field->type == 'text_und'),
845 '#type' => 'select',
846 '#options' => $weights,
847 '#title' => filter_xss(solrsearch_field_name_map($field_name)),
848 '#default_value' => isset($qf[$field_name]) ? $qf[$field_name] : '0',
849 );
850 }
851 }
852
853 // Make sure all the default fields are included, even if they have
854 // no indexed content.
855 foreach ($defaults as $field_name => $weight) {
856 $form['field_bias'][$field_name] = array(
857 '#type' => 'select',
858 '#options' => $weights,
859 '#title' => check_plain(solrsearch_field_name_map($field_name)),
860 '#default_value' => isset($qf[$field_name]) ? $qf[$field_name] : $defaults[$field_name],
861 );
862 }
863
864 ksort($form['field_bias']);
865 }
866 return $form;
867 }
868
869 /**
870 * Form builder function to set query type weights.
871 */
872 function solrsearch_search_type_boost_form($env_id) {
873
874 $form['type_boost'] = array(
875 '#type' => 'fieldset',
876 '#title' => t('Type biasing'),
877 '#collapsible' => TRUE,
878 '#collapsed' => FALSE,
879 '#group' => 'bias_tabs',
880 );
881 $form['type_boost']['solrsearch_search_type_boosts'] = array(
882 '#type' => 'item',
883 '#description' => t("Specify here which node types should get a higher relevancy score in searches. Any value except <em>Ignore</em> will increase the score of the given type in search results."),
884 '#tree' => TRUE,
885 );
886
887 $weights = drupal_map_assoc(array('21.0', '13.0', '8.0', '5.0', '3.0', '2.0', '1.0', '0.8', '0.5', '0.3', '0.2', '0.1'));
888 $weights['0'] = t('Ignore');
889
890 // Get the current boost values.
891 $type_boosts = solrsearch_environment_variable_get($env_id, 'solrsearch_search_type_boosts', array());
892 $names = array();
893 foreach (entity_get_info() as $entity_type => $entity_info) {
894 if (!empty($entity_info['solrsearch']['indexable'])) {
895 foreach ($entity_info['bundles'] as $key => $info) {
896 $names[$key] = $info['label'];
897 }
898 }
899 }
900 asort($names);
901
902 foreach ($names as $type => $name) {
903 $form['type_boost']['solrsearch_search_type_boosts'][$type] = array(
904 '#type' => 'select',
905 '#title' => t('%type type content bias', array('%type' => $name)),
906 '#options' => $weights,
907 '#default_value' => isset($type_boosts[$type]) ? $type_boosts[$type] : 0,
908 );
909 }
910
911 return $form;
912 }
913
914 /**
915 * MoreLikeThis administration and utility functions.
916 */
917 function solrsearch_search_mlt_add_block_form() {
918 $form = solrsearch_search_mlt_block_form();
919 $form['submit'] = array(
920 '#type' => 'submit',
921 '#value' => t('Save'),
922 '#weight' => '5',
923 );
924 return $form;
925 }
926
927 function solrsearch_search_mlt_add_block_form_submit($form, &$form_state) {
928 solrsearch_search_mlt_save_block($form_state['values']);
929 $block_message = t('New More like this block created. <a href="!configure">Configure</a> this block in the Block administration', array('!configure' => url('admin/structure/block')));
930 drupal_set_message($block_message);
931 $form_state['redirect'] = 'admin/config/search/solrsearch/search-pages';
932 }
933
934 /**
935 * Merge supplied settings with the standard defaults..
936 */
937 function solrsearch_search_mlt_block_defaults($block = array()) {
938 return $block + array(
939 'name' => '',
940 'num_results' => '5',
941 'mlt_fl' => array(
942 'label' => 'label',
943 'taxonomy_names' => 'taxonomy_names',
944 ),
945 'mlt_env_id' => 'solr',
946 'mlt_mintf' => '1',
947 'mlt_mindf' => '1',
948 'mlt_minwl' => '3',
949 'mlt_maxwl' => '15',
950 'mlt_maxqt' => '20',
951 'mlt_type_filters' => array(),
952 'mlt_custom_filters' => '',
953 );
954 }
955
956 /**
957 * Constructs a list of field names used on the settings form.
958 *
959 * @return array An array containing a the fields in the solr instance.
960 */
961 function solrsearch_search_mlt_get_fields() {
962 $rows = array();
963
964 try {
965 $solr = solrsearch_get_solr();
966 $fields = $solr->getFields();
967 foreach ($fields as $field_name => $field) {
968 if ($field->schema{4} == 'V') {
969 $rows[$field_name] = solrsearch_field_name_map($field_name);
970 }
971 }
972 ksort($rows);
973 }
974 catch (Exception $e) {
975 watchdog('Apache Solr', nl2br(check_plain($e->getMessage())), NULL, WATCHDOG_ERROR);
976 }
977
978 return $rows;
979 }
980
981 /**
982 * A helper function to save MLT block data.
983 *
984 * If passed a block delta, the function will update block settings. If it is
985 * not passed a block delta, the function will create a new block.
986 *
987 * @param array $block_settings An array containing the settings required to form
988 * a moreLikeThis request.
989 *
990 * @param int $delta The id of the block you wish to update.
991 */
992 function solrsearch_search_mlt_save_block($block_settings = array(), $delta = NULL) {
993 $blocks = variable_get('solrsearch_search_mlt_blocks', array());
994 if (is_null($delta)) {
995 $count = 0;
996 ksort($blocks);
997 // Construct a new array key.
998 if (end($blocks)) {
999 list(, $count) = explode('-', key($blocks));
1000 }
1001 $delta = sprintf('mlt-%03d', 1 + $count);
1002 }
1003 $defaults = solrsearch_search_mlt_block_defaults();
1004 // Remove stray form values.
1005 $blocks[$delta] = array_intersect_key($block_settings, $defaults) + $defaults;
1006 // Eliminate non-selected fields.
1007 $blocks[$delta]['mlt_fl'] = array_filter($blocks[$delta]['mlt_fl']);
1008 $blocks[$delta]['delta'] = $delta;
1009 $blocks[$delta]['mlt_type_filters'] = array_filter($blocks[$delta]['mlt_type_filters']);
1010 $blocks[$delta]['mlt_custom_filters'] = trim($blocks[$delta]['mlt_custom_filters']);
1011 variable_set('solrsearch_search_mlt_blocks', $blocks);
1012 }
1013
1014 function solrsearch_search_mlt_delete_block_form($form, &$form_state, $block) {
1015 if ($block) {
1016 // Backwards compatibility for the block deltas
1017 if (isset($block['delta'])) {
1018 $delta = $block['delta'];
1019 }
1020 else {
1021 $delta = arg(6);
1022 }
1023 // Add our delta to the delete form
1024 $form['delta'] = array(
1025 '#type' => 'value',
1026 '#value' => $delta,
1027 );
1028 $question = t('Are you sure you want to delete the "More Like this" block %name?', array('%name' => $block['name']));
1029 $path = 'admin/structure/block';
1030 $description = t('The block will be deleted. This action cannot be undone.');
1031 $yes = t('Delete');
1032 $no = t('Cancel');
1033 return confirm_form($form, filter_xss($question), $path, $description, $yes, $no);
1034 }
1035 }
1036
1037 function solrsearch_search_mlt_delete_block_form_submit($form, &$form_state) {
1038 $blocks = solrsearch_search_load_all_mlt_blocks();
1039
1040 unset($blocks[$form_state['values']['delta']]);
1041 variable_set('solrsearch_search_mlt_blocks', $blocks);
1042 drupal_set_message(t('The block has been deleted.'));
1043 $form_state['redirect'] = 'admin/config/search/solrsearch/search-pages';
1044 }
1045
1046 /**
1047 * Form to edit moreLikeThis block settings.
1048 *
1049 * @param int $delta If editing, the id of the block to edit.
1050 *
1051 * @return array The form used for editing.
1052 * @todo Add term boost settings.
1053 * @todo Enable the user to specify a query, rather then forcing suggestions
1054 * based on the node id.
1055 */
1056 function solrsearch_search_mlt_block_form($block_id = NULL) {
1057
1058 if (!empty($block_id)) {
1059 $block = solrsearch_search_mlt_block_load($block_id);
1060 if (!$block) {
1061 return array();
1062 }
1063 }
1064 else {
1065 $block = solrsearch_search_mlt_block_defaults();
1066 }
1067
1068 $form['delta'] = array(
1069 '#type' => 'value',
1070 '#default_value' => isset($block['delta']) ? $block['delta'] : '',
1071 '#weight' => '-2',
1072 );
1073
1074 $form['name'] = array(
1075 '#type' => 'textfield',
1076 '#title' => t('Block name'),
1077 '#description' => t('The block name displayed to site users.'),
1078 '#required' => TRUE,
1079 '#default_value' => isset($block['name']) ? $block['name'] : '',
1080 '#weight' => '-2',
1081 );
1082
1083 $environments = solrsearch_load_all_environments();
1084 $options = array('' => t('<Disabled>'));
1085 foreach ($environments as $id => $environment) {
1086 $options[$id] = $environment['name'];
1087 }
1088 $form['mlt_env_id'] = array(
1089 '#title' => t('Search environment'),
1090 '#type' => 'select',
1091 '#options' => $options,
1092 '#default_value' => isset($block['mlt_env_id']) ? $block['mlt_env_id'] : solrsearch_default_environment(),
1093 );
1094
1095 $form['num_results'] = array(
1096 '#type' => 'select',
1097 '#title' => t('Maximum number of related items to display'),
1098 '#default_value' => isset($block['num_results']) ? $block['num_results'] : '',
1099 '#options' => drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)),
1100 '#weight' => -1,
1101
1102 );
1103 /*
1104 *
1105 $form['mlt_fl'] = array(
1106 '#type' => 'checkboxes',
1107 '#title' => t('Fields for finding related content'),
1108 '#description' => t('Choose the fields to be used in calculating similarity. The default combination of %taxonomy_names and %title will provide relevant results for typical sites.', array("%taxonomy_names" => solrsearch_field_name_map("taxonomy_names"), "%title" => solrsearch_field_name_map("label"))),
1109 '#options' => solrsearch_search_mlt_get_fields(),
1110 '#required' => TRUE,
1111 '#default_value' => isset($block['mlt_fl']) ? $block['mlt_fl'] : '',
1112 );
1113 */
1114 $form['advanced'] = array(
1115 '#type' => 'fieldset',
1116 '#title' => t('Advanced configuration'),
1117 '#weight' => '1',
1118 '#collapsible' => TRUE,
1119 '#collapsed' => TRUE,
1120 );
1121 $options = drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7));
1122 /*$form['advanced']['mlt_mintf'] = array(
1123 '#type' => 'select',
1124 '#title' => t('Minimum term frequency'),
1125 '#description' => t('A word must appear this many times in any given document before the document is considered relevant for comparison.'),
1126 '#default_value' => isset($block['mlt_mintf']) ? $block['mlt_mintf'] : '',
1127 '#options' => $options,
1128 );
1129 $form['advanced']['mlt_mindf'] = array(
1130 '#type' => 'select',
1131 '#title' => t('Minimum document frequency'),
1132 '#description' => t('A word must occur in at least this many documents before it will be used for similarity comparison.'),
1133 '#default_value' => isset($block['mlt_mindf']) ? $block['mlt_mindf'] : '',
1134 '#options' => $options,
1135 );
1136 $form['advanced']['mlt_minwl'] = array(
1137 '#type' => 'select',
1138 '#title' => t('Minimum word length'),
1139 '#description' => 'You can use this to eliminate short words such as "the" and "it" from similarity comparisons. Words must be at least this number of characters or they will be ignored.',
1140 '#default_value' => isset($block['mlt_minwl']) ? $block['mlt_minwl'] : '',
1141 '#options' => $options,
1142 );
1143 $form['advanced']['mlt_maxwl'] = array(
1144 '#type' => 'select',
1145 '#title' => t('Maximum word length'),
1146 '#description' => t('You can use this to eliminate very long words from similarity comparisons. Words of more than this number of characters will be ignored.'),
1147 '#default_value' => isset($block['mlt_maxwl']) ? $block['mlt_maxwl'] : '',
1148 '#options' => drupal_map_assoc(array(8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)),
1149 );
1150 $form['advanced']['mlt_maxqt'] = array(
1151 '#type' => 'select',
1152 '#title' => t('Maximum number of query terms'),
1153 '#description' => t('The maximum number of query terms that will be included in any query. Lower numbers will result in fewer recommendations but will get results faster. If a content recommendation is not returning any recommendations, you can either check more "Comparison fields" checkboxes or increase the maximum number of query terms here.'),
1154 '#options' => drupal_map_assoc(array(3, 5, 7, 10, 12, 15, 20, 25, 30, 35, 40)),
1155 '#default_value' => isset($block['mlt_maxqt']) ? $block['mlt_maxqt'] : '',
1156 );
1157 */
1158 /*
1159 $form['restrictions'] = array(
1160 '#type' => 'fieldset',
1161 '#title' => t('Filters'),
1162 '#weight' => '1',
1163 '#collapsible' => TRUE,
1164 '#collapsed' => TRUE,
1165 );
1166
1167 $type_options = array();
1168 foreach (node_type_get_types() as $key => $type) {
1169 $type_options[$key] = $type->name;
1170 }
1171
1172 $form['restrictions']['mlt_type_filters'] = array(
1173 '#type' => 'checkboxes',
1174 '#title' => t('Content Types'),
1175 '#default_value' => is_array($block['mlt_type_filters']) ? $block['mlt_type_filters'] : array(),
1176 '#options' => $type_options,
1177 '#description' => t('Select the content types that similarity suggestions should be restricted to. Multiple types are joined with an OR query, so selecting more types results in more recommendations. If none are selected, no filter will be applied.'),
1178 '#weight' => '-2',
1179 );
1180
1181 $form['restrictions']['mlt_custom_filters'] = array(
1182 '#type' => 'textfield',
1183 '#title' => t('Additional Query'),
1184 '#description' => t("A query, in Lucene syntax, which will further filter the similarity suggestions. For example, 'label:strategy' will filter related content further to only those with strategy in the title. Here are some more examples:") .
1185 '<ul>
1186 <li>ss_language:fr</li>
1187 <li>tid:(5 OR 7)</li>
1188 <li>ds_created:[2009-05-01T23:59:59Z TO 2009-07-28T12:30:00Z]</li>
1189 <li>-is_uid:0, -is_uid:1</li>
1190 </ul>',
1191 '#required' => FALSE,
1192 '#default_value' => isset($block['mlt_custom_filters']) ? $block['mlt_custom_filters'] : '',
1193 '#weight' => '-1',
1194 );
1195 */
1196 return $form;
1197 }