'Custom Search',
'description' => 'Customize the default search, change labels, default texts, ordering, and display content types and taxonomy selectors.',
'page callback' => 'drupal_get_form',
'page arguments' => array('custom_search_admin'),
'access arguments' => array('administer custom search'),
'file' => 'custom_search.admin.inc',
);
$items['admin/config/search/custom_search/settings'] = array(
'title' => 'Settings',
'description' => 'Change the labels, the default texts and the ordering of elements.',
'access arguments' => array('administer custom search'),
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => 0,
);
$items['admin/config/search/custom_search/content'] = array(
'title' => 'Content',
'description' => 'Select the content types to present as search options in the search block.',
'page arguments' => array('custom_search_content_admin'),
'access arguments' => array('administer custom search'),
'file' => 'custom_search.admin.inc',
'type' => MENU_LOCAL_TASK,
'weight' => 1,
);
$items['admin/config/search/custom_search/results'] = array(
'title' => 'Results page',
'description' => 'Customize the search results page.',
'page arguments' => array('custom_search_results_admin'),
'access arguments' => array('administer custom search'),
'file' => 'custom_search.admin.inc',
'type' => MENU_LOCAL_TASK,
'weight' => 4,
);
return $items;
}
/**
* Implements hook_permission().
*/
function custom_search_permission() {
return array(
'administer custom search' => array(
'title' => t('Administer custom search'),
'description' => t('Allow users to administer custom search settings')
),
'use custom search' => array(
'title' => t('Use custom search'),
'description' => t('Allow users to use custom search')
)
);
}
/**
* Implements hook_form_alter().
*/
function custom_search_form_alter(&$form, &$form_state, $form_id) {
if (user_access('use custom search')) {
switch ($form_id) {
case 'search_form':
// Apply Custom Search settings to the advanced search form.
if (!variable_get('custom_search_advanced_or_display', TRUE)) unset($form['advanced']['keywords']['or']);
if (!variable_get('custom_search_advanced_phrase_display', TRUE)) unset($form['advanced']['keywords']['phrase']);
if (!variable_get('custom_search_advanced_negative_display', TRUE)) unset($form['advanced']['keywords']['negative']);
$names = array_keys(node_type_get_names());
foreach ($names as $name) {
if (!variable_get('custom_search_advanced_type_' . $name . '_display', TRUE)) unset($form['advanced']['type']['#options'][$name]);
}
if (!count($form['advanced']['type']['#options'])) unset($form['advanced']['type']);
if (!variable_get('custom_search_results_search', TRUE)) {
// If basic search is hidded, original search terms are imported into advanced search.
$original_keys = $form['basic']['keys']['#default_value'];
$temp_keys = explode(' ', $original_keys);
foreach ($temp_keys as $value) {
if (drupal_substr($value, 0, 5) != 'type:' && drupal_substr($value, 0, 5) != 'term:') $keys[] = $value;
}
$form['advanced']['keywords']['or']['#default_value'] = implode(' ', $keys);
if (!isset($GLOBALS['custom_search_nb_results']) || (isset($GLOBALS['custom_search_nb_results']) && !$GLOBALS['custom_search_nb_results'])) $form['advanced']['#collapsed'] = FALSE;
$form['basic']['#prefix'] = '
';
$form['basic']['#suffix'] = '
';
}
if (!variable_get('custom_search_results_advanced_search', TRUE)) unset($form['advanced']);
break;
case 'search_theme_form':
case 'search_block_form':
case 'custom_search_blocks_form':
$delta = ($form_id == 'custom_search_blocks_form') ? 'blocks_' . $form['delta']['#value'] . '_' : '';
// Title.
$form[$form_id]['#title'] = variable_get('custom_search_' . $delta . 'label', CUSTOM_SEARCH_LABEL_DEFAULT);
if (!variable_get('custom_search_' . $delta . 'label_visibility', FALSE)) $form[$form_id]['#post_render'] = array('_custom_search_hide_label');
// Search box.
$form[$form_id]['#default_value'] = variable_get('custom_search_' . $delta . 'text', '');
$form[$form_id]['#weight'] = variable_get('custom_search_' . $delta . 'search_box_weight', 0);
$form[$form_id]['#attributes'] = array('class' => array('custom-search-default-value', 'custom-search-box'));
// Default text.
$form['default_text'] = array(
'#type' => 'hidden',
'#default_value' => variable_get('custom_search_' . $delta . 'text', ''),
'#attributes' => array('class' => array('default-text')),
);
// CSS
$path = drupal_get_path('module', 'custom_search');
drupal_add_css($path . '/custom_search.css');
if ($form_id != 'custom_search_blocks_form') {
// Criteria
if (variable_get('custom_search_criteria_or_display', FALSE)) {
$form['custom_search_criteria_or'] = array(
'#type' => 'textfield',
'#title' => variable_get('custom_search_criteria_or_label', CUSTOM_SEARCH_CRITERIA_OR_LABEL_DEFAULT),
'#size' => 15,
'#maxlength' => 255,
'#weight' => variable_get('custom_search_criteria_or_weight', 6),
);
}
if (variable_get('custom_search_criteria_phrase_display', FALSE)) {
$form['custom_search_criteria_phrase'] = array(
'#type' => 'textfield',
'#title' => variable_get('custom_search_criteria_phrase_label', CUSTOM_SEARCH_CRITERIA_PHRASE_LABEL_DEFAULT),
'#size' => 15,
'#maxlength' => 255,
'#weight' => variable_get('custom_search_criteria_phrase_weight', 7),
);
}
if (variable_get('custom_search_criteria_negative_display', FALSE)) {
$form['custom_search_criteria_negative'] = array(
'#type' => 'textfield',
'#title' => variable_get('custom_search_criteria_negative_label', CUSTOM_SEARCH_CRITERIA_NEGATIVE_LABEL_DEFAULT),
'#size' => 15,
'#maxlength' => 255,
'#weight' => variable_get('custom_search_criteria_negative_weight', 8),
);
}
}
// Content type & other searches.
// Content types.
$toptions = array();
$types = array_keys(array_filter(variable_get('custom_search_' . $delta . 'node_types', array())));
if (count($types)) {
$names = node_type_get_names();
if (count($types) > 1 || variable_get('custom_search_' . $delta . 'any_force', FALSE)) $toptions['c-all'] = variable_get('custom_search_' . $delta . 'type_selector_all', CUSTOM_SEARCH_ALL_TEXT_DEFAULT);
foreach ($types as $type) {
$toptions['c-' . $type] = $names[$type];
}
}
$options = array();
// Other searches.
$others = array_keys(array_filter(variable_get('custom_search_' . $delta . 'other', array())));
// If content types and other searches are combined, make an optgroup.
if (count($others) && count($toptions) && variable_get('custom_search_' . $delta . 'type_selector', 'select') == 'select') {
$content = module_invoke('node', 'search_info');
$options[$content['title']] = $toptions;
}
else {
$options = $toptions;
}
foreach (module_implements('search_info') as $module) {
if ($module != 'node' && $name = module_invoke($module, 'search_info')) {
if (in_array($module, $others)) $options['o-' . $module] = $name['title'];
}
}
if (count($options)) {
$selector_type = variable_get('custom_search_' . $delta . 'type_selector', 'select');
if ($selector_type == 'selectmultiple') {
$selector_type = 'select';
$multiple = TRUE;
}
else $multiple = FALSE;
$form['custom_search_types'] = array(
'#type' => $selector_type,
'#multiple' => $multiple,
'#title' => variable_get('custom_search_' . $delta . 'type_selector_label', CUSTOM_SEARCH_TYPE_SELECTOR_LABEL_DEFAULT),
'#options' => $options,
'#default_value' => ((variable_get('custom_search_' . $delta . 'type_selector', 'select') == 'checkboxes') ? array('c-all') : 'c-all'),
'#attributes' => array('class' => array('custom-search-selector', 'custom-search-types')),
'#weight' => variable_get('custom_search_' . $delta . 'content_types_weight', 1),
'#validated' => TRUE,
);
// If there's only one type, hide the selector
if (count($others) + count($types) == 1 && !variable_get('custom_search_' . $delta . 'any_force', FALSE)) {
$form['custom_search_types']['#type'] = 'hidden';
$default_value = array_keys(array_slice($options, count($options)-1));
$form['custom_search_types']['#default_value'] = $default_value[0];
}
if (!variable_get('custom_search_' . $delta . 'type_selector_label_visibility', TRUE)) $form['custom_search_types']['#post_render'] = array('_custom_search_hide_label');
}
// Custom paths
if (variable_get('custom_search_' . $delta . 'paths', '') != '') {
$options = array();
$lines = explode("\n", variable_get('custom_search_' . $delta . 'paths', ''));
foreach ($lines as $line) {
$temp = explode('|', $line);
$options[$temp[0]] = $temp[1];
}
if (count($options) == 1) {
$form['custom_search_paths'] = array(
'#type' => 'hidden',
'#default_value' => $temp[0],
);
}
else {
$form['custom_search_paths'] = array(
'#type' => 'select',
'#options' => $options,
'#weight' => variable_get('custom_search_' . $delta . 'paths', 9),
);
}
}
// Submit button.
$form['actions']['submit']['#value'] = variable_get('custom_search_submit_text', CUSTOM_SEARCH_SUBMIT_TEXT_DEFAULT);
if (variable_get('custom_search_image_path', '') != '') {
$form['actions']['submit']['#type'] = 'image_button';
$form['actions']['submit']['#src'] = variable_get('custom_search_image_path', '');
$form['actions']['submit']['#name'] = 'op';
$form['actions']['submit']['#attributes'] = array('alt' => array(variable_get('custom_search_submit_text', CUSTOM_SEARCH_SUBMIT_TEXT_DEFAULT)));
$form['actions']['submit']['#attributes'] = array('class' => 'custom-search-button');
}
elseif ($form['actions']['submit']['#value'] == '') $form['actions']['submit']['#attributes'] = array('style' => 'display:none;');
$form['actions']['submit']['#weight'] = variable_get('custom_search_' . $delta . 'submit_button_weight', 3);
// Form attributes
drupal_add_js(array('custom_search_target' => variable_get('custom_search_target', '_self')), array('type' => 'setting'));
$form['#attributes']['class'] = array('search-form');
$form['#submit'][] = 'custom_search_submit';
$form['form_token']['#default_value'] = drupal_get_token($form_id);
break;
}
}
}
/**
* Alter the search to respect the search modes selected.
*/
function custom_search_submit($form, &$form_state) {
$delta = (isset($form_state['values']['delta'])) ? 'blocks_' . $form_state['values']['delta'] . '_' : '' ;
variable_set('custom_search_delta', $delta); // save for later use (exclusion & refresh)
$type = 'node';
$keys = $form_state['values'][$form_state['values']['form_id']];
$types = (isset($form_state['values']['custom_search_types'])) ? $form_state['values']['custom_search_types'] : array();
if (!is_array($types)) $types = array($types);
$types = array_map('_custom_search_filter_keys', array_filter($types));
if (module_exists('taxonomy')) {
$terms = array();
$vocabularies = taxonomy_get_vocabularies();
foreach ($vocabularies as $voc) {
if (isset($form_state['values']['custom_search_vocabulary_' . $voc->vid])) {
$vterms = $form_state['values']['custom_search_vocabulary_' . $voc->vid];
if (!is_array($vterms)) $vterms = array($vterms);
$terms = array_merge($terms, $vterms);
}
}
$terms = array_map('_custom_search_filter_keys', array_values(array_filter($terms)));
// if one or more -Any- is selected, delete them
while (($index = array_search('all', $terms)) !== FALSE) array_splice($terms, $index, 1);
}
$search_types = module_implements('search_info');
$values = array_values($types); // temp transform of the array to have numerical index for the next test
if (count($values) && in_array($values[0], $search_types)) {
$type = $values[0];
}
else {
if (isset($form_state['values']['custom_search_criteria_or']) && trim($form_state['values']['custom_search_criteria_or']) != '') $keys .= ' ' . str_replace(' ', ' OR ', trim($form_state['values']['custom_search_criteria_or']));
if (isset($form_state['values']['custom_search_criteria_negative']) && trim($form_state['values']['custom_search_criteria_negative']) != '') $keys .= ' -' . str_replace(' ', ' -', trim($form_state['values']['custom_search_criteria_negative']));
if (isset($form_state['values']['custom_search_criteria_phrase']) && trim($form_state['values']['custom_search_criteria_phrase']) != '') $keys .= ' "' . trim($form_state['values']['custom_search_criteria_phrase']) . '"';
if (count($types)) {
// If a content type is selected, and it's not -Any-, search for that type.
if (!in_array('all', $types)) $keys = search_expression_insert($keys, 'type', implode(',', $types));
// If -Any- is selected and -Any- is set to restrict the search, grab the content types.
elseif (variable_get('custom_search_' . $delta . 'any_restricts', FALSE)) {
$restricted_types = array_keys(array_filter(variable_get('custom_search_' . $delta . 'node_types', array())));
$keys = search_expression_insert($keys, 'type', implode(',', $restricted_types));
}
}
if (module_exists('taxonomy') && count($terms)) {
$keys = search_expression_insert($keys, 'term', implode(',', $terms));
}
}
if (module_exists('apachesolr_search')) $type = 'apachesolr_search';
elseif (module_exists('google_appliance')) $type = variable_get('google_appliance_default_search_path', 'google-appliance');
elseif (module_exists('luceneapi_node') && variable_get('luceneapi:default_search', 0)) $type = variable_get('luceneapi:default_search', 0);
if (isset($form_state['values']['custom_search_paths']) && $form_state['values']['custom_search_paths'] != '') {
// build the custom path
$custom_path = str_replace('[key]', $form_state['values'][$form_state['values']['form_id']], $form_state['values']['custom_search_paths']);
if ($terms_token_pos = strpos($form_state['values']['custom_search_paths'], '[terms-')) {
$terms_separator = drupal_substr($form_state['values']['custom_search_paths'], $terms_token_pos + 7, strpos($form_state['values']['custom_search_paths'], ']', $terms_token_pos) - $terms_token_pos - 7);
$custom_path = drupal_substr($custom_path, 0, strpos($custom_path, '[terms-')) . ((count($terms)) ? implode($terms_separator, $terms) : '') . drupal_substr($custom_path, strpos($custom_path, ']', strpos($custom_path, '[terms-')) + 1);
}
$form_state['redirect'] = $custom_path;
}
else $form_state['redirect'] = 'search/' . $type . '/' . $keys;
}
/*
* Rewrite the sql query to exclude content types.
*/
function custom_search_query_alter(QueryAlterableInterface $query) {
if ($query->hasTag('node_access') && $query->hasTag('pager')) {
$excluded_types = array_filter(variable_get('custom_search_' . variable_get('custom_search_delta', '') . 'node_types_excluded', array()));
if (!empty($excluded_types)) {
$tables = $query->getTables();
foreach ($tables as $table) {
if ($table['table'] == 'search_index') {
$query->condition('n.type', $excluded_types, 'NOT IN');
}
}
}
}
}
/**
* Implements hook_init().
*/
function custom_search_init() {
if (user_access('use custom search')) {
drupal_add_js(drupal_get_path('module', 'custom_search') . '/custom_search.js');
}
}
/**
* Implements hook_theme().
*/
function custom_search_theme() {
if (user_access('use custom search')) {
return array(
'custom_search_javascript' => array(
'variables' => array(),
),
'custom_search_sort_form' => array(
'render element' => 'form',
),
'search_result' => array(
'variables' => array('result' => NULL, 'module' => NULL),
'file' => 'custom_search.pages.inc',
'template' => 'custom_search-result',
),
'search_results' => array(
'variables' => array('results' => NULL, 'module' => NULL),
'file' => 'custom_search.pages.inc',
'template' => 'custom_search-results',
),
);
}
else return array();
}
/**
* Content admin form.
*/
function custom_search_content_admin_form($delta = '') {
if ($delta != '') $delta = 'blocks_' . $delta . '_';
$form['content_selector'] = array(
'#type' => 'fieldset',
'#title' => t('Content selector'),
'#description' => t('Select the search types to present as search options in the search block. If none is selected, no selector will be displayed. Note: if there\'s only one type checked, the selector won\'t be displayed BUT only this type will be searched.'),
);
$form['content_selector']['custom_search_' . $delta . 'node_types'] = array(
'#type' => 'checkboxes',
'#title' => t('Content types'),
'#default_value' => variable_get('custom_search_' . $delta . 'node_types', array()),
'#options' => node_type_get_names(),
);
// Other searches.
$options = array();
foreach (module_implements('search_info') as $module) {
if ($module != 'node' && $name = module_invoke($module, 'search_info')) {
$options[$module] = $name['title'];
}
}
if (count($options)) {
$form['content_selector']['custom_search_' . $delta . 'other'] = array(
'#type' => 'checkboxes',
'#title' => t('Other searches'),
'#default_value' => variable_get('custom_search_' . $delta . 'other', array()),
'#options' => $options,
);
}
$form['content_selector']['custom_search_' . $delta . 'type_selector'] = array(
'#type' => 'select',
'#title' => t('Selector type'),
'#options' => array(
'select' => t('Drop-down list'),
'selectmultiple' => t('Drop-down list with multiple choices'),
'radios' => t('Radio buttons'),
'checkboxes' => t('Checkboxes'),
),
'#description' => t('Choose which selector type to use. Note: content types and other searches cannot be combined in a single search.'),
'#default_value' => variable_get('custom_search_' . $delta . 'type_selector', 'select'),
);
$form['content_selector']['custom_search_' . $delta . 'type_selector_label_visibility'] = array(
'#type' => 'checkbox',
'#title' => t('Display label'),
'#default_value' => variable_get('custom_search_' . $delta . 'type_selector_label_visibility', TRUE),
);
$form['content_selector']['custom_search_' . $delta . 'type_selector_label'] = array(
'#type' => 'textfield',
'#title' => t('Label text'),
'#default_value' => variable_get('custom_search_' . $delta . 'type_selector_label', CUSTOM_SEARCH_TYPE_SELECTOR_LABEL_DEFAULT),
'#description' => t('Enter the label text for the selector. The default value is "!default".', array('!default' => CUSTOM_SEARCH_TYPE_SELECTOR_LABEL_DEFAULT)),
);
$form['content_selector']['any'] = array(
'#type' => 'fieldset',
'#title' => t('-Any-'),
);
$form['content_selector']['any']['custom_search_' . $delta . 'type_selector_all'] = array(
'#type' => 'textfield',
'#title' => t('-Any content type- text'),
'#default_value' => variable_get('custom_search_' . $delta . 'type_selector_all', CUSTOM_SEARCH_ALL_TEXT_DEFAULT),
'#required' => TRUE,
'#description' => t('Enter the text for "any content type" choice. The default value is "!default".', array('!default' => CUSTOM_SEARCH_ALL_TEXT_DEFAULT)),
);
$form['content_selector']['any']['custom_search_' . $delta . 'any_restricts'] = array(
'#type' => 'checkbox',
'#title' => t('Choosing -Any- restricts the search to the selected content types.'),
'#default_value' => variable_get('custom_search_' . $delta . 'any_restricts', FALSE),
'#description' => t('If not checked, choosing -Any- will search in all content types.'),
);
$form['content_selector']['any']['custom_search_' . $delta . 'any_force'] = array(
'#type' => 'checkbox',
'#title' => t('Force -Any- to be displayed.'),
'#default_value' => variable_get('custom_search_' . $delta . 'any_force', FALSE),
'#description' => t('When only one content type is selected, the default behaviour is to hide the selector. If you need the -Any- option to be displayed, check this.'),
);
$form['custom_search_' . $delta . 'node_types_excluded'] = array(
'#type' => 'checkboxes',
'#title' => t('Content exclusion'),
'#description' => t('Select the content types you don\'t want to be displayed as results.'),
'#default_value' => variable_get('custom_search_' . $delta . 'node_types_excluded', array()),
'#options' => node_type_get_names(),
);
return $form;
}
/**
* Custom paths admin form.
*/
function custom_search_custom_paths_admin_form($delta = '') {
if ($delta != '') $delta = 'blocks_' . $delta . '_';
$form['custom_search_' . $delta . 'paths'] = array(
'#type' => 'textarea',
'#title' => t('Custom search paths'),
'#default_value' => variable_get('custom_search_' . $delta . 'paths', ''),
'#description' => t('If you want to use a custom search paths, enter them here in the form path|label, one per line. If only one path is specified, the selector will be hidden.
The [key] token will be replaced by what is entered in the search box, and the [terms-] token will be replaced by the selected taxonomy term id(s). If multiple taxonomy terms are selected, they will be separated by what you include between "[terms-" and the closing "]".
Ie: mysearch/[key]/[terms-,]|My custom search label.'),
);
return $form;
}
/**
* Filter the types
*/
function _custom_search_filter_keys($val) {
return drupal_substr($val, 2);
}
/**
* Remove the label by adding a class.
*/
function _custom_search_hide_label($content, $elements) {
if (strpos($content, '