'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) { // Filter the form_id value to identify all the custom blocks. $form_id_processed = $form_id; $delta = ''; for ($a = 1; $a <= variable_get('custom_search_blocks_number', 1); $a++) { if ($form_id == 'custom_search_blocks_form_' . $a) { $form_id_processed = 'custom_search_blocks_form'; $delta = 'blocks_' . $a . '_'; } } switch ($form_id_processed) { case 'search_form': if (isset($form['module']) && $form['module']['#value'] == 'node') { if (isset($form['advanced'])) { // Criteria. if (!variable_get('custom_search_advanced_or_display', TRUE)) { $form['advanced']['keywords']['or']['#type'] = 'hidden'; } if (!variable_get('custom_search_advanced_phrase_display', TRUE)) { $form['advanced']['keywords']['phrase']['#type'] = 'hidden'; } if (!variable_get('custom_search_advanced_negative_display', TRUE)) { $form['advanced']['keywords']['negative']['#type'] = 'hidden'; } // Content types. $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']['#type']); } // Languages. foreach (language_list('language') as $key => $entity) { if ($entity->enabled) { $language_options[$key] = $entity->name; } } if (count($language_options) > 1) { foreach ($language_options as $key => $name) { if (!variable_get('custom_search_advanced_language_' . $key . '_display', TRUE)) { unset($form['advanced']['language']['#options'][$key]); } } if (!count($form['advanced']['language']['#options'])) { unset($form['advanced']['language']['#type']); } } } if (!variable_get('custom_search_results_search', TRUE)) { if (isset($form['basic']['keys'])) { // If basic search is hidden, import terms 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'] = '
'; } $form['advanced']['#collapsible'] = variable_get('custom_search_results_advanced_search_collapsible', TRUE); $form['advanced']['#collapsed'] = variable_get('custom_search_results_advanced_search_collapsed', TRUE); if (!variable_get('custom_search_results_advanced_search', TRUE)) { $form['advanced']['#type'] = 'hidden'; } } break; case 'search_theme_form': case 'search_block_form': case 'custom_search_blocks_form': if (user_access('use custom search')) { // Title. $form[$form_id]['#title'] = variable_get('custom_search_' . $delta . 'label', CUSTOM_SEARCH_LABEL_DEFAULT); $form[$form_id]['#title_display'] = (!variable_get('custom_search_' . $delta . 'label_visibility', FALSE)) ? 'invisible' : 'before'; // Search box. if (module_exists('elements') && variable_get('custom_search_' . $delta . 'element', 'textfield') != 'textfield') { $form[$form_id]['#type'] = variable_get('custom_search_' . $delta . 'element', 'textfield'); } $form[$form_id]['#weight'] = variable_get('custom_search_' . $delta . 'search_box_weight', 0); $form[$form_id]['#size'] = variable_get('custom_search_' . $delta . 'size', CUSTOM_SEARCH_SIZE_DEFAULT); $form[$form_id]['#maxlength'] = variable_get('custom_search_' . $delta . 'max_length', CUSTOM_SEARCH_MAX_LENGTH_DEFAULT); if (!isset($form[$form_id]['#attributes'])) { $form[$form_id]['#attributes'] = array('class' => array()); } elseif (!isset($form[$form_id]['#attributes']['class'])) { $form[$form_id]['#attributes']['class'] = array(); } $form[$form_id]['#attributes']['class'][] = 'custom-search-box'; $form[$form_id]['#attributes']['placeholder'] = variable_get('custom_search_' . $delta . 'text', ''); $form[$form_id]['#attributes']['title'] = variable_get('custom_search_' . $delta . 'hint_text', CUSTOM_SEARCH_HINT_TEXT_DEFAULT); // CSS. drupal_add_css(drupal_get_path('module', 'custom_search') . '/custom_search.css'); // Criteria. $criteria = array('or' => 6, 'phrase' => 7, 'negative' => 8); foreach ($criteria as $c => $w) { if (variable_get('custom_search_' . $delta . 'criteria_' . $c . '_display', FALSE)) { $form['custom_search_criteria_' . $c] = array( '#type' => 'textfield', '#title' => variable_get('custom_search_' . $delta . 'criteria_' . $c . '_label', constant('CUSTOM_SEARCH_CRITERIA_' . strtoupper($c) . '_LABEL_DEFAULT')), '#size' => 15, '#maxlength' => 255, '#weight' => variable_get('custom_search_' . $delta . 'criteria_' . $c . '_weight', $w), ); } } // 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] = t($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'; $form['custom_search_types']['#default_value'] = key(array_slice($options, count($options) - 1)); } if (!variable_get('custom_search_' . $delta . 'type_selector_label_visibility', TRUE)) { $form['custom_search_types']['#title_display'] = 'invisible'; } } // 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]] = (count($temp) >= 2) ? t($temp[1]) : ''; } if (count($options) == 1) { $form['custom_search_paths'] = array( '#type' => 'hidden', '#default_value' => key($options), ); } else { $form['custom_search_paths'] = array( '#type' => variable_get('custom_search_' . $delta . 'paths_selector', 'select'), '#title' => variable_get('custom_search_' . $delta . 'paths_selector_label', CUSTOM_SEARCH_PATHS_SELECTOR_LABEL_DEFAULT), '#options' => $options, '#default_value' => key($options), '#weight' => variable_get('custom_search_' . $delta . 'custom_paths_weight', 9), ); if (!variable_get('custom_search_' . $delta . 'paths_selector_label_visibility', TRUE)) { $form['custom_search_paths']['#title_display'] = 'invisible'; } } } // Submit button. $form['actions']['submit']['#value'] = variable_get('custom_search_' . $delta . 'submit_text', CUSTOM_SEARCH_SUBMIT_TEXT_DEFAULT); if (variable_get('custom_search_' . $delta . 'image_path', '') != '') { $form['actions']['submit']['#type'] = 'image_button'; $form['actions']['submit']['#src'] = variable_get('custom_search_' . $delta . 'image_path', ''); $form['actions']['submit']['#name'] = 'op'; $form['actions']['submit']['#attributes'] = array( 'alt' => array(variable_get('custom_search_' . $delta . 'submit_text', CUSTOM_SEARCH_SUBMIT_TEXT_DEFAULT)), 'class' => array('custom-search-button'), ); unset($form['actions']['submit']['#value']); } elseif ($form['actions']['submit']['#value'] == '') { $form['actions']['submit']['#attributes'] = array('style' => 'display:none;'); } $form['actions']['#weight'] = variable_get('custom_search_' . $delta . 'submit_button_weight', 3); // Popup. $form['popup'] = array( '#type' => 'fieldset', '#weight' => 1 + variable_get('custom_search_' . $delta . 'search_box_weight', 0), '#attributes' => array('class' => array('custom_search-popup')), ); if (!empty($form['custom_search_types']) && variable_get('custom_search_' . $delta . 'content_types_region', 'block') == 'popup') { $form['popup']['custom_search_types'] = $form['custom_search_types']; unset($form['custom_search_types']); } if (!empty($form['custom_search_paths']) && variable_get('custom_search_' . $delta . 'custom_paths_region', 'block') == 'popup') { $form['popup']['custom_search_paths'] = $form['custom_search_paths']; unset($form['custom_search_paths']); } foreach ($criteria as $c => $w) { if (variable_get('custom_search_' . $delta . 'criteria_' . $c . '_display', FALSE) && variable_get('custom_search_' . $delta . 'criteria_' . $c . '_region', 'block') == 'popup') { $form['popup']['custom_search_criteria_' . $c] = $form['custom_search_criteria_' . $c]; unset($form['custom_search_criteria_' . $c]); } } // Invoke other modules hooks. foreach (module_implements('custom_search_box') as $module) { $function = $module . '_custom_search_box'; if (function_exists($function)) { call_user_func_array($function, array(&$form, $form_id, $delta)); } } // If nothing has been added to the popup, don't output any markup. if (!count(element_children($form['popup']))) { unset($form['popup']); } // Form attributes. $form['#attributes']['class'] = array('search-form'); $form['#attributes']['role'] = 'search'; if (!in_array('custom_search_submit', $form['#submit'])) { $form['#submit'][] = 'custom_search_submit'; } } break; } } /** * Alter the search to respect the search modes selected. */ function custom_search_submit($form, &$form_state) { // Save delta for later use (exclusion & refresh). $delta = (isset($form_state['values']['delta'])) ? 'blocks_' . $form_state['values']['delta'] . '_' : ''; variable_set('custom_search_delta', $delta); $type = 'node'; $keys = $form_state['values'][$form_state['values']['form_id']]; $original_keywords = $keys; $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); } } // Invoke other modules hooks. $other = array(); foreach (module_implements('custom_search_filter') as $module) { $function = $module . '_custom_search_filter'; if (function_exists($function)) { $other = call_user_func_array($function, array($form, $form_state, $other)); } } $search_types = module_implements('search_info'); if (in_array(current($types), $search_types)) { $type = current($types); $info = module_invoke($type, 'search_info'); $path = (isset($info['path'])) ? $info['path'] : $type; } else { $path = $type; 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']) . '"'; } $original_keywords = $keys; 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)) { $types = array_keys(array_filter(variable_get('custom_search_' . $delta . 'node_types', array()))); $keys = search_expression_insert($keys, 'type', implode(',', $types)); } } if (module_exists('taxonomy') && count($terms)) { $keys = search_expression_insert($keys, 'term', implode(',', $terms)); } if (module_exists('custom_search_i18n')) { $i18n_search_language = variable_get('custom_search_i18n_search_language', 'all'); if ($i18n_search_language == 'current') { $keys = search_expression_insert($keys, 'language', i18n_language()->language); } elseif ($i18n_search_language == 'current_neutral') { $keys = search_expression_insert($keys, 'language', i18n_language()->language . ',und'); } } } $search_path = array( 'path' => 'search/' . $path . '/' . $keys, 'query' => array(), ); // Integrates other search modules. if (module_exists('apachesolr_search')) { $fields = field_info_fields(); for ($i = 0; $i < count($types); $i++) { // Remove the item from the array if it's not a content type. if (!in_array($types[$i], array_keys(node_type_get_types()))) { unset($types[$i]); } } $search_path = _custom_search_apachesolr_search(array( 'keywords' => $original_keywords, 'types' => $types, 'terms' => (!empty($terms)) ? $terms : array(), 'other' => (!empty($other)) ? $other : array(), ), $keys, $fields); } elseif (module_exists('google_appliance')) { $search_path = _custom_search_google_appliance_search(array( 'keys' => $keys, )); } elseif (module_exists('luceneapi_node') && variable_get('luceneapi:default_search', 0)) { $search_path = _custom_search_lucenapi_search(array( 'keywords' => $original_keywords, 'types' => $types, 'terms' => (!empty($terms)) ? $terms : array(), )); } elseif (module_exists('search_api_page')) { $search_api_page = search_api_page_load(variable_get('custom_search_' . $delta . 'search_api_page', 0)); if ($search_api_page) { $search_path = _custom_search_search_api_search(array( 'keywords' => $original_keywords, 'types' => $types, 'terms' => (!empty($terms)) ? $terms : array(), 'page' => $search_api_page, )); } } // Build a custom path if needed. if (isset($form_state['values']['custom_search_paths']) && $form_state['values']['custom_search_paths'] != '') { $custom_path = str_replace('[key]', $form_state['values'][$form_state['values']['form_id']], $form_state['values']['custom_search_paths']); $custom_path = str_replace('[current_path]', current_path(), $custom_path); if (strpos($form_state['values']['custom_search_paths'], '[terms]') !== FALSE) { $custom_path = str_replace('[terms]', (count($terms)) ? implode($form_state['values']['custom_search_paths_terms_separator'], $terms) : '', $custom_path); } // Check for a query string. $custom_path_query_position = strpos($custom_path, '?'); $custom_path_query = array(); if ($custom_path_query_position !== FALSE) { $custom_path_query_tmp = substr($custom_path, 1 + $custom_path_query_position); $custom_path_query_tmp = str_replace('&', '&', $custom_path_query_tmp); $custom_path_query_tmp = explode('&', $custom_path_query_tmp); foreach ($custom_path_query_tmp as $param) { $param_exploded = explode('=', $param); $custom_path_query[$param_exploded[0]] = $param_exploded[1]; } $custom_path = substr($custom_path, 0, $custom_path_query_position); } // Check for external path. If not, add base path. if (drupal_substr($custom_path, 0, 4) != 'http') { $custom_path = url($custom_path, array('absolute' => TRUE)); } // Send the final url. $form_state['redirect'] = url($custom_path, array('query' => $custom_path_query, 'absolute' => TRUE)); } else { $form_state['redirect'] = url($search_path['path'], array('query' => $search_path['query'], 'absolute' => TRUE)); } } /* * Rewrite the sql query to exclude content types. */ function custom_search_query_alter(QueryAlterableInterface $query) { if (!$query->hasTag('custom_search_ignore') && $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_block_view_alter(). * Used to exclude Facet API searching for excluded types. */ function custom_search_block_view_alter(&$data, $block) { if ($block->module == 'facetapi') { $excluded_types = array_filter(variable_get('custom_search_' . variable_get('custom_search_delta', '') . 'node_types_excluded', array())); if (!empty($excluded_types) && isset($data['content']['bundle']) && is_array($data['content']['bundle']["#items"])) { foreach ($data['content']['bundle']["#items"] as $key => $item) { // Find the type in the link. preg_match('/ array( 'form_target' => variable_get('custom_search_target', '_self'), 'solr' => (module_exists('apachesolr_search') || module_exists('search_api_solr')) ? 1 : 0, ), ), array('type' => 'setting')); } } /** * Implements hook_theme(). */ function custom_search_theme() { $path = drupal_get_path('module', 'custom_search') . '/theme'; $custom_search_theme_array = array( 'custom_search_javascript' => array( 'variables' => array(), ), 'custom_search_sort_form' => array( 'render element' => 'form', 'path' => $path, 'template' => 'custom_search-sort-form', ), 'search_result' => array( 'variables' => array('result' => NULL, 'module' => NULL), 'path' => $path, 'file' => 'custom_search.pages.inc', 'template' => 'custom_search-result', ), 'search_results' => array( 'variables' => array('results' => NULL, 'module' => NULL), 'path' => $path, 'file' => 'custom_search.pages.inc', 'template' => 'custom_search-results', ), ); // Panels integration. $router_item = db_query_range('SELECT page_callback FROM {menu_router} WHERE path = :path', 0, 1, array(':path' => 'search/node/%'))->fetchAssoc(); if ($router_item['page_callback'] == 'page_manager_search_page') { unset($custom_search_theme_array['search_results'], $custom_search_theme_array['search_result']); } return $custom_search_theme_array; } /** * Implements hook_link(). */ function custom_search_contextual_links_view_alter(&$element, $items) { if (isset($element['#element']['#form_id']) && ($element['#element']['#form_id'] == 'search_block_form') && user_access('administer custom search')) { $element['#links']['custom_search'] = array( 'title' => t('Custom Search configuration'), 'href' => 'admin/config/search/custom_search', 'query' => drupal_get_destination(), ); } } /** * Filter the types. */ function _custom_search_filter_keys($val) { return (strlen($val) > 2 && $val[1] == '-') ? drupal_substr($val, 2) : $val; } /** * Function used to filter node_type array to only filter * those that are configured in Custom Search Form. */ function custom_search_filter_array($value = FALSE) { return $value !== 0; }