Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Apress.Pro.Drupal.7.Development.3rd.Edition.Dec.2010.pdf
Скачиваний:
54
Добавлен:
14.03.2016
Размер:
12.64 Mб
Скачать

CHAPTER 13 SEARCHING AND INDEXING CONTENT

We’ll look at these hooks in more detail in the sections that follow.

Adding Metadata to Nodes: hook_node_update_index()

When Drupal indexes a node for searching, it first runs the node through node_view(). Modules can decide how the data will be displayed, indicating whether the content should be indexed. For example, assume we have a node with an ID of 26. The parts of the node that are visible when viewing the URL http://example.com/?q=node/26 are what the indexer also sees.

What if we have a custom node type that contains hidden data that needs to influence search results? A good example of where we might want to do this is with book.module. We could index the chapter headings along with each child page to boost the relevancy of those children pages.

/**

* Implements hook_node_update_index(). */

function book_boost_node_update_index($node) {

//Book nodes have a parent link ID attribute.

//If it's nonzero we can have the menu system retrieve

//the parent's menu item which gives us the title.

if ($node->type == 'book' && $node->book['plid']) { $item = menu_link_load($node->book['plid']);

return '<h2>'. $item['title'] .'</h2>';

}

}

}

Notice that we wrapped the title in HTML heading tags to inform the indexer of a higher relative score value for this text.

Note The node_update_index hook is only for appending metadata to nodes. To index elements that aren’t nodes, use hook_update_index().

Indexing Content That Isn’t a Node: hook_update_index()

If you need to wrap the search engine around content that isn’t made up of Drupal nodes, you can hook right into the indexer and feed it any textual data you need, thus making it searchable within Drupal. Suppose your group supports a legacy application that has been used for entering and viewing technical notes about products for the last several years. For political reasons, you cannot yet replace it with a Drupal solution, but you’d love to be able to search those technical notes from within Drupal. No problem. Let’s assume the legacy application keeps its data in a database table called technote. We’ll create a short module that will send the information in this database to Drupal’s indexer using hook_update_index() and present search results using the search hooks.

317

CHAPTER 13 SEARCHING AND INDEXING CONTENT

Note If you’d like to index content from a non-Drupal database, take a look at Chapter 5 for more information on connecting to multiple databases.

Create a folder named legacysearch inside sites/all/modules/custom. If you want to have a legacy database to play with, create a file named legacysearch.install, and add the following contents:

<?php

/**

* Implements hook_install(). */

function legacysearch_install() {

$fields = array('id' => 1, 'title' => 'Web 1.0 Emulator', 'note' => '<p>This handyproduct lets you emulate the blink tag but in hardware...a perfect gift.</p>',

'last_modified' => 1172502517); db_insert('technote')

->fields($fields) ->execute();

$fields = array('id' => 2, 'title' => 'Squishy Debugger', 'note' => '<p>Fullyfunctional debugger inside a squishy gel case. The embedded ARM processor heatsup...</p>', 'last_modified' => 1172502517);

db_insert('technote') ->fields($fields) ->execute();

}

/**

* Implements hook_uninstall(). */

function legacysearch_uninstall() { drupal_uninstall_schema('legacysearch');

}

/**

* Implements hook_schema(). */

function legacysearch_schema() { $schema['technote'] = array(

'description' => t('A database with some example records.'),

318

CHAPTER 13 SEARCHING AND INDEXING CONTENT

'fields' => array( 'id' => array(

'type' => 'serial', 'not null' => TRUE,

'description' => t("The tech note's primary ID."),

),

'title' => array( 'type' => 'varchar', 'length' => 255,

'description' => t("The tech note's title."),

),

'note' => array( 'type' => 'text',

'description' => t('Actual text of tech note.'),

),

'last_modified' => array( 'type' => 'int', 'unsigned' => TRUE,

'description' => t('Unix timestamp of last modification.'),

),

),

'primary key' => array('id'),

);

return $schema;

}

This module typically wouldn’t need this install file, since the legacy database would already exist; we’re just using it to make sure we have a legacy table and data to work with. You would instead adjust the queries within the module to connect to your existing non-Drupal table. The following queries assume the data is in a non-Drupal database with the database connection defined in the $databases array in settings.php.

Next, add sites/all/modules/custom/legacysearch/legacysearch.info with the following content:

name = Legacy Search

description = Example of indexing/searching external content with Drupal. package = Pro Drupal Development

core = 7.x

files[] = legacysearch.install files[] = legacysearch.module

Finally, add sites/all/modules/custom/legacysearch/legacysearch.module along with the following code:

<?php

/**

*@file

*Enables searching of non-Drupal content.

*/

319

Download from Wow! eBook <www.wowebook.com>

CHAPTER 13 SEARCHING AND INDEXING CONTENT

Go ahead and keep legacysearch.module open in your text editor, and we’ll add hook_update_index(), which feeds the legacy data to the HTML indexer. You can now safely enable your module after creating these files. You will also need to go to admin/config/search/settings and enable legacy_search as one of the active search modules and after saving, click the Re-index site to rebuild the indexes including the legacy search.

/**

* Implements hook_search_info() */

function legacysearch_search_info() { return array(

'title' => 'Tech Notes',

);

}

/**

* Implements hook_search_reset() */

function legacysearch_search_reset() { variable_del('legacysearch_cron_last_change'); variable_del('legacysearch_cron_last_id'); return;

}

/**

* Shutdown function to make sure we remember the last element processed. */

function legacysearch_update_shutdown() { global $last_change, $last_id;

if ($last_change && $last_id) { variable_set('legacysearch_cron_last_change', $last_change); variable_set('legacysearch_cron_last_id', $last_id);

}

}

/**

* Implements hook_update_index(). */

function legacysearch_update_index() {

global $last_change, $last_id; register_shutdown_function('legacysearch_update_shutdown');

$last_id = variable_get('legacysearch_cron_last_id', 0); $last_change = variable_get('legacysearch_cron_last_change', 0);

db_set_active('legacy');

320

CHAPTER 13 SEARCHING AND INDEXING CONTENT

$result = db_query("SELECT id, title, note, last_modified FROM {technote} WHERE id >

:last_id OR last_modified > :last_change",

array(':last_id' => $last_id, ':last_change' => $last_change));

db_set_active('default');

foreach($result as $data) { $last_change = $data->last_modified; $last_id = $data->id;

$text = '<h1>' . check_plain($data->title) . '</h1>' . $data->note; search_index($data->id, 'technote', $text); variable_set('legacysearch_cron_last', $data->last_modified); variable_set('legacysearch_cron_last_id', $data->id);

}

}

/**

* Implements hook_search_execute(). */

function legacysearch_search_execute($keys = NULL) {

//Set up a mock URL to embed in the link so that when the user clicks it takes themto the legacy site

$legacy_url = 'http://technotes.example.com';

//Set up and execute the query

$query = db_select('search_index', 'i')->extend('SearchQuery')->extend('PagerDefault'); $query->join('technote', 't', 't.id = i.sid');

$query

->searchExpression($keys, 'technote');

//If there weren't any results then return a blank result set if (!$query->executeFirstPass()) {

return array();

}

//If the first pass did return at least one record then execute the search $found = $query

->limit(10) ->execute();

//Now create the search results output

foreach ($found as $item) {

// First get the values from the legacy table to display in search results db_set_active('legacy');

$note = db_query("SELECT * FROM {technote} where id = :sid", array(':sid' =>$item->sid));

db_set_active('default');

321

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]