相关项目使用Drupal 6搜索阻止
相关项目块查看页面的当前内容,并尝试向用户显示与当前内容相关的项目列表。创建相关项块非常容易,并且是引入搜索模块api的好方法,而无需参与搜索模块。
在开始之前,我应该指出,还有其他相关项目模块可用。这些模块像“相关节点”或“相关项目”一样,但是这些模块不是针对Drupal6发行的,或者根本无法按照我希望该块起作用的方式工作。我想要一个几乎不需要用户输入就可以运行的模块。
我们创建的模块将包含4个文件,.info文件,.module文件和两个模板文件。我将在这里依次浏览每个文件,但是我还将在文章底部添加一个下载链接,您可以在其中将所有文件下载为一个模块。
首先要做的是(在module文件夹中创建一个文件夹之后)创建一个名为relateditems.info的文件。该文件告诉Drupal模块的名称和描述是什么,并且还添加了一个依赖项,该依赖项告诉Drupal该功能需要搜索模块。
name = Related Items description = Provides the functionality needed to create a related items block. core = 6.x dependencies[] = search
接下来,创建一个名为relateditems.module的文件。这是Drupal在运行模块时将查找的主要模块文件。我没有将文件分成很多位,而是在代码中添加了很多注释,以便清楚地了解发生了什么。该relateditems_block()函数挂接到Drupal的块制作代码中,并允许定义一个或多个块。搜索是在relateditems_query()函数中完成的,该函数从当前节点获取标题和预告片,提取最常用的关键字,然后使用它们进行搜索。我们仅使用标题和预告片,因为它们通常具有较高比例的好关键字,并且将减少PHP必须执行的字符串处理量。
这是relateditems.module完整的文件。
array(
'arguments' => array(
'item' => NULL),
'template' => 'relateditems-item',
),
//定义列表包装器的主题。
'relateditems_block' => array(
'arguments' => array(
'items' => NULL),
'template' => 'relateditems-content',
),
);
}
/**
* Take a text string and extract the most commonly used keywords. The keywords
* are returned in a format that is compatable with Drupal search. The function
* also contains a list of stop words that can be used to remove junk words.
*
* @param string $content The content that the keywords are to be extracted from.
* @param integer $count The number of keywords to be extracted.
*
* @return string The
*/
function relateditems_node_content_keywords($content, $count = 5)
{
//从内容中剥离HTML标记并转换为小写。
$content = strtolower(strip_tags($content));
//停用词列表
$stopWords = array('i','a','about','an','are','as','at','be','by','com',
'for','from','has','how','in','is','it','of','on','or','nbsp','that',
'the','this','to','was','what','when','where','who','will','with',
'the','www','were',);
//过滤掉停用词。
$filterCount = count($stopWords);
for($i=0; $i < $filterCount; $i++){
$content = preg_replace('/\b'.$stopWords[$i].'\b/i', "", $content);
}
//计算单词数。
$words = array_count_values(str_word_count($content, 1));
//对单词进行排序,以使最受欢迎的单词位于顶部。
arsort($words);
//对数组进行切片,然后将单词array转换为字符串。
return implode(' OR ', array_keys(array_slice($words, 0, $count)));
}
/**
* This function is called by the relateditems_render() function. It finds the
* content of the current node and uses this to search for nodes that match
* this content.
*
* @return array The array of nodes found through the search.
*/
function relateditems_query()
{
if (arg(0)=='node' && is_numeric(arg(1))) {
//我们正在查看一个节点页面,因此请加载节点内容。
$current_node = node_load(arg(1));
//将标题和预告片合并为一个变量,然后提取关键字。
$content = $current_node->title . ' ' . $current_node->teaser;
$words = relateditems_node_content_keywords($content);
//对关键字进行搜索。
$searched_nodes = node_search('search', $words);
//返回找到的节点。
return $searched_nodes;
}
}
/**
* This function calls relateditems_query() and renders the results as a list.
*
* @return string The rendered output.
*/
function relateditems_render()
{
//查找要渲染的节点。
$nodes = relateditems_query();
$items = array();
$output = '';
if (count($nodes) > 0) {
//如果我们有多个节点,则开始渲染。
//渲染节点。
foreach ($nodes as $node) {
$items[] = theme('relateditems_item', $node);
}
//渲染整体输出。
$output .= theme('relateditems_block', $items);
} else {
//如果未找到任何项目,则返回简单消息。
$output .= 'No Related Items Found
';
}
//返回输出。
return $output;
}所有这些要注意的一件事是,我最初尝试使用一个名为的函数do_search(),但是为了使该函数正确运行,必须将其传递10个参数,这可能需要花点时间才能解决。然后,我遇到了一种通过使用适当命名的node_search()函数来搜索节点的更简单,更有效的方法。node_search()函数的第一个参数是我们要执行的操作的类型,在这种情况下,我们要搜索,因此我们使用“搜索”操作。
使用该node_search()函数使过滤之类的事情变得可能且非常简单。例如,假设我们希望将找到的节点仅限制为“博客”类型的节点,这可以通过对node_search()函数进行以下更改来完成。
$searched_nodes=node_search('search','type:blog'.$words);
我们还可以使用关键字“类别”将搜索词限制为特定的分类词。
最后,我们需要创建两个模板文件,模块使用它们来对输出进行主题化。第一个文件称为relateditems-content.tpl.php,其中包含以下内容:
所需的最终文件称为relateditems-item.tpl.php,其中包含以下内容:
如果需要,您可以在此处下载整个模块。