Extending Drupal 7 search

后端 未结 1 1974
醉酒成梦
醉酒成梦 2020-12-30 16:46

I want to extend default Drupal 7 node search with one additional field.

I alter search form with the following new field:



        
相关标签:
1条回答
  • 2020-12-30 17:31

    The following is the best way I solve this problem.

    First of all I need to alter Drupal's search block and search form with my field and define new submit function.

    /**
     * Implements hook_form_FORM_ID_alter().
     */
    function mymodule_form_search_block_form_alter(&$form, &$form_state, $form_id) {
        $form['#submit'][] = 'search_form_alter_submit';
    
        $form['site'] = array(
            '#type' => 'select',
            '#options' => _options(),
            '#default_value' => (($_GET['site']) ? $_GET['site'] : '')
        );
    }
    
    /**
     * Implements hook_form_FORM_ID_alter().
     */
    function mymodule_form_search_form_alter(&$form, &$form_state, $form_id) {
        $form['#submit'][] = 'search_form_alter_submit';
    
        $form['basic']['site'] = array(
            '#type' => 'select',
            '#options' => _options(),
            '#default_value' => (($_GET['site']) ? $_GET['site'] : '')
        );
    }
    
    function _options() {
        return array(
            '' => 'Select site',
            'site-1' => 'Site 1',
            'site-2' => 'Site 2'
        );
    }
    

    Submit function will forward us to default search/node page but with our query. Page would look like search/node/Our-query-string?site=Our-option-selected.

    function search_form_alter_submit($form, &$form_state) {
        $path = $form_state['redirect'];
        $options = array(
            'query' => array(
                'site' => $form_state['values']['site']
            )
        );
        drupal_goto($path, $options);
    }
    

    Next step is to use hook_search_info (Don't forget to turn it on and set as default on admin/config/search/settings page).

    /**
     * Implements hook_search_info().
     */
    function mymodule_search_info() {
        return array(
            'title' => 'Content',
            'path' => 'node',
            'conditions_callback' => '_conditions_callback',
        );
    }
    

    Conditions callback function defined in hook_search_info. We need to provide additional queries to our search.

    function _conditions_callback($keys) {
        $conditions = array();
        if (!empty($_REQUEST['site'])) {
            $conditions['site'] = $_REQUEST['site'];
        }
        return $conditions;
    }
    

    Finally, hook_search_execute will filter our content by our query. I used default code from this hook with modifications I need.

    /**
     * Implements hook_search_execute().
     */
    function mymodule_search_execute($keys = NULL, $conditions = NULL) {
        // Build matching conditions
        $query = db_select('search_index', 'i', array('target' => 'slave'))
            ->extend('SearchQuery')
            ->extend('PagerDefault');
    
        $query->join('node', 'n', 'n.nid = i.sid');
    
        // Here goes my filter where I joined another table and
        // filter by required field
        $site = (isset($conditions['site'])) ? $conditions['site'] : NULL;
        if ($site) {
            $query->leftJoin('field_data_field_site', 's', 's.entity_id = i.sid');
            $query->condition('s.field_site_value', $site);
        }
        // End of my filter
    
        $query
            ->condition('n.status', 1)
            ->addTag('node_access')
            ->searchExpression($keys, 'node');
    
        // Insert special keywords.
        $query->setOption('type', 'n.type');
        $query->setOption('language', 'n.language');
        if ($query->setOption('term', 'ti.tid')) {
            $query->join('taxonomy_index', 'ti', 'n.nid = ti.nid');
        }
    
        // Only continue if the first pass query matches.
        if (!$query->executeFirstPass()) {
            return array();
        }
    
        // Add the ranking expressions.
        _node_rankings($query);
    
        // Load results.
        $find = $query
            ->limit(10)
            ->execute();
    
        $results = array();
        foreach ($find as $item) {
            // Build the node body.
            $node = node_load($item->sid);
            node_build_content($node, 'search_result');
            $node->body = drupal_render($node->content);
    
            // Fetch comments for snippet.
            $node->rendered .= ' ' . module_invoke('comment', 'node_update_index', $node);
            // Fetch terms for snippet.
            $node->rendered .= ' ' . module_invoke('taxonomy', 'node_update_index', $node);
    
            $extra = module_invoke_all('node_search_result', $node);
    
            $results[] = array(
                'link' => url("node/{$item->sid}", array('absolute' => TRUE)),
                'type' => check_plain(node_type_get_name($node)),
                'title' => $node->title,
                'user' => theme('username', array('account' => $node)),
                'date' => $node->changed,
                'node' => $node,
                'extra' => $extra,
                'score' => $item->calculated_score,
                'snippet' => search_excerpt($keys, $node->body)
            );
        }
    
        return $results;
    }
    

    I'd be happy if anyone would give me a better answer.

    0 讨论(0)
提交回复
热议问题