在Drupal 6搜索中过滤节点类型

在Drupal中创建站点的常见做法是为不同的目的创建不同的节点类型。有时,这些节点类型可以基于功能而不是基于内容,并用于创建旋转的横幅或类似内容。这样做的副作用是您将看到这些节点出现在搜索结果中,这可能会导致显示一些令人困惑的结果。

那么,如何删除这些节点?通过一个非常简单的小模块,您可以拦截搜索查询并停止搜索某些节点类型。添加几个额外的功能意味着我们可以将表单控件添加到高级搜索表单和搜索管理区域,以便可以选择节点以将其从搜索结果中排除。

首先,在您的sites / all / modules目录中为模块(我称其为searchfilter)以及一个信息文件创建一个文件夹。我们需要向搜索模块添加一个依赖项,以便当搜索模块不存在时,该模块不会引起任何怪异的副作用(实际上是错误)。这是searchfilter.info文件。

; $Id$
 
name = Search filter
description = "Filters out selected content types from search results"
dependencies[] = search
core = 6.x

现在创建一个文件,该文件将存储名为searchfilter.module的模块代码。该文件将包含4个功能,现在我将逐一介绍这些功能。首先要做的是设置权限,以便我们可以限制或允许对节点筛选器的访问。这是的简单实现hook_perm()。

function searchfilter_perm() {
    return array('access searchfilter content');
}

下一步是添加对的调用,HOOK_db_rewrite_sql()以便我们可以拦截搜索查询并添加所需的where子句,以防止我们选择的节点出现在搜索结果中。此功能可确保我们正在查看正确的查询,并为具有“访问searchfilter内容”权限的用户提供绕过的功能。这意味着您可以打开模块,仍然允许某些用户找到他们需要的任何东西。

function searchfilter_db_rewrite_sql($query, $primary_table, $primary_field, $args) {
    // 具有正确权限的用户可以搜索网站上的所有内容。
    if (!user_access('access searchfilter content')) {
        if ($query == '' && $primary_table == 'n' && $primary_field = 'nid' && empty($args)) {
            $excluded_types = variable_get('searchfilter_types', array());
            if (!empty($excluded_types)) {
                $where = "n.typeNOT IN ('" . implode("','", $excluded_types) . "') ";
                return array('where' => $where);
            }
        }
    }
}

为了允许管理员预先选择要排除的节点类型,添加了一个挂钩以更改搜索管理员表单。这将在管理表单的表单底部添加一个选择框,该选择框将仅列出节点类型。

function searchfilter_search($op = 'search') {
	if ('admin' == $op) {
        $form = array();
        $form['searchfilter_types'] = array(
            '#type'          => 'select',
            '#multiple'      => TRUE,
            '#title'                => t('Exclude Node Types'),
            '#default_value' => variable_get('searchfilter_types', array()),
            '#options'       => node_get_types('names'),
            '#size'          => 9,
            '#description'   => t('Node types to exclude from search results.'),
        );
        return $form;
    }
}

最后一步是在主搜索表单中添加一个选项(针对具有权限的用户),该选项将允许用户从每个可用的节点类型中进行选择,而不仅仅是允许的节点类型。

function searchfilter_form_alter(&$form, &$form_state, $form_id) {
    if ('search_form' == $form_id) {
        if (!user_access('access searchfilter content')) {
            $excluded_types = variable_get('searchfilter_types', array());
            $types = array_map('check_plain', node_get_types('names'));
            foreach ($excluded_types as $excluded_type) {
                unset($types[$excluded_type]);
            }
            $form['advanced']['type']['#options'] = $types;
        }
    }
}

将这两个文件放置到位后,您将能够激活该模块并将过滤器添加到您的搜索结果中。

为了方便起见,下面是完整的汇编代码。

<?php
// $Id $
 
/**
 * @file
 */
 
/**
 * Implementation of HOOK_perm().
 *
 * @return array An array of the permissions for this module.
 */
function searchfilter_perm() {
    return array('access searchfilter content');
}
 
/**
 * Implementation of HOOK_db_rewrite_sql. Rewrite the search database query and 
 * add in the node types that have been selected.
 *
 * @param string $query         Query to be rewritten.
 * @param string $primary_table Name or alias of the table which has the primary key field for this query. 
 * @param string $primary_field Name of the primary field.
 * @param array  $args          Array of additional arguments.
 * 
 * @return array The addition to the where statement to be used by the search
 *               query.
 */
function searchfilter_db_rewrite_sql($query, $primary_table, $primary_field, $args) {
    // 具有正确权限的用户可以搜索网站上的所有内容。
    if (!user_access('access searchfilter content')) {
        if ($query == '' && $primary_table == 'n' && $primary_field = 'nid' && empty($args)) {
            $excluded_types = variable_get('searchfilter_types', array());
            if (!empty($excluded_types)) {
                $where = "n.typeNOT IN ('" . implode("','", $excluded_types) . "') ";
                return array('where' => $where);
            }
        }
    }
}
 
/**
 * Implementation of HOOK_search, allows the addition of a form component to our
 * search admin interface.
 *
 * @return array The additional form component.
 */
function searchfilter_search($op = 'search') {
	if ('admin' == $op) {
        $form = array();
        $form['searchfilter_types'] = array(
            '#type'          => 'select',
            '#multiple'      => TRUE,
            '#title'         => t('Exclude Node Types'),
            '#default_value' => variable_get('searchfilter_types', array()),
            '#options'       => node_get_types('names'),
            '#size'          => 9,
            '#description'   => t('Node types to exclude from search results.'),
        );
        return $form;
    }
}
 
/**
 * Implementation of HOOK_form_alter. Alter the search form to restrict the 
 * selectable node types to just the list that has been saved.
 * 
 * @param array  $form       Nested array of form elements that comprise the form.
 * @param array  $form_state A keyed array containing the current state of the form.
 * @param string $form_id    String representing the name of the form itself.
 */
function searchfilter_form_alter(&$form, &$form_state, $form_id) {
    if ('search_form' == $form_id) {
        if (!user_access('access searchfilter content')) {
            $excluded_types = variable_get('searchfilter_types', array());
            $types = array_map('check_plain', node_get_types('names'));
            foreach ($excluded_types as $excluded_type) {
                unset($types[$excluded_type]);
            }
            $form['advanced']['type']['#options'] = $types;
        }
    }
}